Java线程的等待与唤醒
生产者和消费者必须使用同步代码块包裹起来,保证等待和唤醒只能有一个执行,同步使用的锁对象必须保证唯一
Thread中重要方法
void wait() 在其他线程调用此对象的notify()方法或notifyall()方法前,导致当前线程等待
void notify() 唤醒在此对象监视器上等待的单个线程后,会继续执行wait方法之后的代码
void notifyAll() 唤醒所有等待线程
void wait(long m)在毫秒结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/blocke状态
void sleep(long m)在毫秒结束之后,线程睡醒进入到Runnable/blocke状态
使用
我们自己创建线程类的子类时,不要忘了写上继承extend。再run()方法中写入线程同步的代码,在客户端调用时,直接调用start方法,默认自动调用run方法的代码。
实例
产品类
public class Product {
//属性代表该产品是否还有
boolean flag=false;
}
//生产者类
public class Producer extends Thread{
private Product pr;
//构造有参构造函数,让产品类实例的对象作为锁对象
public Producer(Product pr){
this.pr=pr;
}
@Override
public void run() {
//一直生产该商品
while (true){
//使用锁对象
synchronized (pr){
//如果该产品还存在,
if(pr.flag==true){
try {
//生产者停止生产
pr.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//否则生产者开始生产
System.out.println("生产者正在生产");
try {
//生产时间为5秒
Thread.sleep(5000);
System.out.println("请等待5秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
//生产完成
pr.flag=true;
//唤醒消费者
pr.notify();
System.out.println("生产者生产完了,消费之开始使用");
}
}
}
}
//消费者类
public class Consumer extends Thread{
private Product pr;
//郑州人流医院 http://mobile.zzzzyy120.com/
public Consumer(Product pr){
this.pr=pr;
}
@Override
public void run() {
//消费者一直消费产品
while (true){
//锁对象
synchronized (pr){
//如果产品没有了
if (pr.flag==false){
try {
//则消费者进行等待
pr.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果产品还有,消费者使用产品
System.out.println("消费者正在使用");
//消耗完产品,改变产品属性
pr.flag=false;
//唤醒生产者,等待再次生产产品
pr.notify();
System.out.println("产品已经使用完了,生产者开始生产");
}
}
}
}
//主函数
public static void main(String[] args) {
//实例化产品
Product pr=new Product();
//实例化生产者,并运行run方法
new Producer(pr).start();
//实例化消费者,并运行run方法
new Consumer(pr).start();
}
运行结果