Java第二十五天,多线程之等待唤醒机制
当线程被创建并且被启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,而是具有以下多种状态:
这六种状态之间的转换关系如下:
1.等待唤醒机制
注意:
(1)两个线程之间必须用同步代码块给包裹起来,保证等待和唤醒线程同一时间段只能有一个执行,用以保证共享数据安全。
(2)同步使用的锁对象必须是同一个对象。
(3)必须使用锁对象的wait()和notify()方法完成等待唤醒的操作。
(4)要注意多个被synchronized修饰的代码块是只允许在同一时刻运行一个;也就是说如果要和循环(特别是死循环)配合使用的话,要注意二者之间的包含关系。
代码:
package com.lanyue.day25;
public class Consumer extends Thread{
Resource r = null;
public void setLock(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
synchronized (r){
try {
r.wait();
} catch (InterruptedException e) {
System.out.println("系统发生奔溃");
}
try {
System.out.println("消费中======>");
Thread.sleep(1000);
r.num--;
r.isEmpty = true;
System.out.println("当前货物剩余量:" + r.num);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("系统奔溃");
}
}
}
}
}
package com.lanyue.day25;
public class Producer extends Thread{
Resource r = null;
public void setLock(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
synchronized (r){
if(r.isEmpty){
try {
System.out.println("生产中======>");
Thread.sleep(1000);
r.num++;
r.isEmpty = false;
System.out.println("当前货物剩余量:" + r.num);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("系统奔溃");
}
}else{
r.notify();
}
}
}
}
}
package com.lanyue.day25;
public class Resource {
public boolean isEmpty = true;
public Integer num = 0;
}
package com.lanyue.day25;
public class TestDemo {
public static void main(String[] args) {
Resource r = new Resource();
Producer in = new Producer();
Consumer out = new Consumer();
in.setLock(r);
out.setLock(r);
in.start();
out.start();
}
}
很多人会纳闷为什么是
while(true){
synchronized(obj){
}
}
而不是
synchronized(obj){
whle(true){ } }
因为如果是后者,将会导致同一时刻只能执行一个死循环,言外之意也就是说会导致另一个死循环停止执行,不再是所谓的死循环。两个线程也仅仅只会留下一个。