线程状态
线程有6种状态:
(1)NEW:新建状态,至今尚未启动的线程处于这种状态。 new Thread( ) ; new Thread子类( ) ;
(2)RUNNABLE:运行状态,正在Java虚拟机中执行的线程属于这种状态。 start( )
(3)BLOCKED:阻塞状态,受阻塞并等待某个监视器锁的线程处于这种状态。
(4)WAITING:无限(永久)等待状态,无限期地等待另一个线程来执行某一待定操作的线程处于这种状态。 Object.wait( ) Object.notify( )
(5)TIMED_WAITING:休眠(睡眠)状态,等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。 sleep( long) wait( long)
(6)TERMINATED:死亡状态,已退出的线程处于这种状态。 run( ) 方法结束 stop( ) 过时
【阻塞状态:具有cpu的执行资格,等待cpu空闲时执行
休眠状态:放弃cpu的执行资格,cpu空闲,也不执行
休眠状态和无限等待状态是冻结状态】
等待唤醒案例:线程之间的通信
创建一个顾客线程(消费者):告知老板要的包子种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)
创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子
注意:
顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
同步使用的锁对象必须保证唯一
只有锁对象才能调用wait和notify方法
例如: Object obj = new Object( ) ;
Object类中的方法
(1)void wait( ) 在其他线程调用此对象的notify( ) 方法或notifyAll( ) 方法前,导致当前线程等待。
例如:
new Thread( ) {
@Override
public void run( ) {
synchronized ( obj) {
try {
obj.wait( ) ;
} catch ( InterruptedException e) {
e.printStackTrace( ) ;
}
}
}
} .start( ) ;
(2)void notify( ) 唤醒在此对象监视器上等待的单个线程。
注意:会继续执行wait方法之后的代码。
例如:
new Thread( ) {
@Override
public void run( ) {
synchronized ( obj) {
obj.notify( ) ;
}
}
} .start( ) ;
等待与唤醒
进入到TimeWaiting( 及时等待) 有两种方式
1. 使用sleep( long m) 方法,在毫秒值结束之后,线程睡醒进入到Runnable/Blocked状态
例如:
try {
Thread.sleep( 5000) ;
} catch ( InterruptedException e) {
e.printStackTrace( ) ;
}
2. 使用wait( long m) 方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/Blocked状态
例如:
try {
obj.wait( 5000) ;
} catch ( InterruptedException e) {
e.printStackTrace( ) ;
}
唤醒的方法:
(1)void notify( ) 唤醒在此对象监视器上等待的单个线程。
例如: obj.notify( ) ; // 如果有多个等待线程,随机唤醒一个
(2)void notifyAll( ) 唤醒在此对象监视器上等待的所有线程。
例如: obj.notifyAll( ) ; // 唤醒所有等待的线程
等待与唤醒机制:线程之间的通信
重点:有效的利用资源(生产一个包子,吃一个包子,再生产一个包子,再吃一个包子.. .)
通信:对包子的状态进行判断
没有包子--> 吃货线程唤醒包子铺线程--> 吃货线程等待--> 包子铺线程做包子--> 做好包子--> 修改包子的状态为【有】
有包子--> 包子铺线程唤醒吃货线程--> 包子铺线程等待--> 吃货吃包子--> 吃完包子--> 修改包子的状态为【没有】
没有包子--> 吃货线程唤醒包子铺线程--> 吃货线程等待--> 包子铺线程做包子--> 做好包子--> 修改包子的状态为【有】
.. .
1. wait方法与notify方法必须要由同一个锁对象调用。
因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程。
2. wait方法与notify方法是属于Object类的方法。
因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的。
3. wait方法与notify方法必须要在同步代码块或者是同步函数中使用。
因为:必须要通过锁对象调用这2个方法。
资源类:包子类
设置包子的属性
皮
陷
包子的状态:有--> true,没有--> false
生产者(包子铺)类:是一个线程类,可以继承Thread
设置线程任务(run):生产包子
对包子的状态进行判断
true:有包子
包子铺调用wait方法进入等待状态
false:没有包子
包子铺生成包子
增加一些趣味性:交替生成两种包子
有两种状态(i%2== 0)
包子铺生产好了包子
修改包子的状态为true有
唤醒吃货线程,让吃货线程吃包子
消费者(吃货)类:是一个线程类,可以继承Thread
设置线程任务(run):吃包子
对包子的状态进行判断
false:没有包子
吃货线程调用wait方法进入等待状态
true:有包子
吃货吃包子
吃货吃完包子
修改包子的状态为false没有
吃货唤醒包子铺线程,生产包子
测试类:
包含main方法,程序执行的入口,启动程序
创建包子对象;
创建包子铺线程,开启;
创建吃货线程,开启;