线程状态
new:线程尚未启动的状态
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
* 研究的是新建线程的状态
* 新建状态:至今还未启动的线程处于这一状态
*/
public class ThreadState01 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
//创建线程对象
MyThread01 my = new MyThread01();
System.out.println("此时的线程状态:"+my.getState());
//调用run方法,非启动线程
my.run();
System.out.println("此时的线程状态:"+my.getState());
//启动线程
my.start();
System.out.println("此时的线程状态:"+my.getState());
}
}
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
public class MyThread01 extends Thread{
/**线程执行的代码*/
@Override
public void run() {
System.out.println("小猫爱吃鱼");
}
}
runnable:可运行的状态
这里的可运行的状态,包括正在执行,或者正在等待,比如等待获取CPU的执行权,或者等待I/O,都属于可运行状态,这个要和进程的状态区分开来。
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
public class Demo02 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
//创建线程对象
MyThread02 my = new MyThread02();
System.out.println("此时的线程状态:"+my.getState());
//启动线程
my.start();
System.out.println("此时的线程状态:"+my.getState());
}
}
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
public class MyThread02 extends Thread{
/**线程执行的代码*/
@Override
public void run() {
System.out.println("线程开始执行");
System.out.println("线程开始执行具体的任务");
long begin_time = System.currentTimeMillis();
while (System.currentTimeMillis()-begin_time < 5000){
//假设做了5秒钟的任务
}
System.out.println("线程执行完毕");
}
}
blocked:锁阻塞的状态
线程安全
多线程卖票
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
/**
* 模拟买票操作
* 假设一场电影有100张票
* 3个窗口同时卖票
*
* 窗口 线程对象
* 卖票 线程任务 实现runnable接口
*/
public class Demo03 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
//创建卖票对象
Ticket ticket = new Ticket();
//创建3个窗口
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//开始卖票
t1.start();
t2.start();
t3.start();
}
}
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
public class Ticket implements Runnable{
int ticket_num = 100;
@Override
public void run() {
while (true){//卖票窗口永远开启
if (ticket_num > 0){
//模拟出票时间
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖第"+ticket_num--+"张票");
}
}
}
}
结果是出现了重复的票,而且还会出现负数的票。
出现负数的票
原因:
ticket_num–分为2个部分,
- 先参与运算
- 然后再–
有可能前面一个线程还没来得及进行–操作,票数没有更新。后一个线程这时候也打印了num。这就是出现重复票的原因。
出现负数的票
因为第一个线程将票数改成0的时候,另外两个线程已经进来了,然后顺势将票数改成0和-1并输出。
线程同步
采用同步代码块实现
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
/**
* 模拟买票操作
* 假设一场电影有100张票
* 3个窗口同时卖票
*
* 窗口 线程对象
* 卖票 线程任务 实现runnable接口
*/
public class Demo03 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
//创建卖票对象
Ticket ticket = new Ticket();
//创建3个窗口
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//开始卖票
t1.start();
t2.start();
t3.start();
}
}
package cn.lizemin.demo.thread;
/**
* @author: lizemin
* @version: 1.0
*/
public class Ticket implements Runnable{
int ticket_num = 100;
Object object = new Object();
@Override
public void run() {
while (true){//卖票窗口永远开启
synchronized (object){
if (ticket_num > 0){
//模拟出票时间
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖第"+ticket_num--+"张票");
}
}
}
}
}
获取block状态
多个线程争夺同一个锁,没有抢到锁的那个线程会进入到阻塞状态,即block.
线程A
package cn.lizemin.demo.thread.blocked;
/**
* @author: lizemin
* @version: 1.0
*/
public class A extends Thread{
private Object obj;
public A(String name,Object obj){
super(name);
this.obj = obj;
}
@Override
public void run() {
synchronized (obj){
System.out.println("线程开始执行");
System.out.println("线程A开始执行代码了");
long begin_time = System.currentTimeMillis();
while (System.currentTimeMillis() - begin_time < 5000){
//模拟5秒钟的任务
}
System.out.println("线程A执行完毕");
}
}
}
线程B
package cn.lizemin.demo.thread.blocked;
/**
* @author: lizemin
* @version: 1.0
*/
public class B extends Thread{
private Object obj;
public B(String name,Object obj){
super(name);
this.obj = obj;
}
@Override
public void run() {
synchronized (obj){
System.out.println("线程开始执行");
System.out.println("线程B开始执行代码了");
long begin_time = System.currentTimeMillis();
while (System.currentTimeMillis() - begin_time < 5000){
//模拟5秒钟的任务
}
System.out.println("线程B执行完毕");
}
}
}
BlockedDemo
package cn.lizemin.demo.thread.blocked;
/**
* @author: lizemin
* @version: 1.0
*/
public class BlockedDemo {
//这是一个main方法,是程序的入口
public static void main(String[] args) throws InterruptedException {
//创建一个锁对象
Object o = new Object();
//创建线程
A a = new A("小强", o);
B b = new B("旺财", o);
a.start();
b.start();
Thread.sleep(3000);
System.out.println("此时线程A的状态:"+a.getState());
System.out.println("此时线程B的状态:"+b.getState());
}
}
最终可以看到
此时线程A的状态:RUNNABLE
此时线程B的状态:BLOCKED
线程B进入阻塞状态
timed waiting:计时等待
比如,thread.sleep(1000)
demo演示
package cn.lizemin.demo.thread.timed_waiting;
/**
* @author: lizemin
* @version: 1.0
*/
public class MyThread extends Thread{
//这是一个main方法,是程序的入口
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
mt.start();
for (int i = 0; i < 10; i++) {
Thread.sleep(500);
System.out.println("线程mt的状态为:"+mt.getState());
}
}
//实现一个计数器,0~99计数,在每个数字之间暂停1秒,每隔10个数字输出一个字符串
@Override
public void run() {
for (int i = 1; i < 99; i++) {
if (i % 10 == 0){
System.out.println("小猫爱吃鱼"+i);
}
System.out.println(i);
try {
/*休息1s*/
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 1; i < 99; i++) {
}
}
}
无限等待:waiting
使当前线程进入无限等待状态,直到其他线程唤醒它,通过notify或者
package cn.lizemin.demo.thread.waiting;
/**
* @author: lizemin
* @version: 1.0
*/
public class WaitingDemo {
private static Object obj = new Object();
//这是一个main方法,是程序的入口
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
synchronized (obj){
System.out.println("获取到锁,调用wait方法,当前线程进入无限等待,等待着别人来唤醒它");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("唤醒了这个线程,就不再是无限等待了,线程执行完毕");
}
};
t.start();
//创建一个线程对象唤醒前面的线程
new Thread(){
@Override
public void run() {
synchronized (obj){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("获取到锁,执行唤醒操作");
obj.notify();
}
}
}.start();
Thread.sleep(3000);
//waiting
System.out.println("查看线程t的状态:"+t.getState());
}
}