等待唤醒机制

等待唤醒机制
在开始讲解等待唤醒机制之前,有必要搞清一个概念——线程之间的通信:
多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。
通过一定的手段使各个线程能有效的利用资源。 而这种手段即—— 等待唤醒机制。
等待唤醒机制所涉及到的方法: wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。 notify():
唤醒,唤醒线程池中被 wait()的线程,一次唤醒一个,而且是任意的。
notify(): 唤醒全部:可以将线程池中的所有 wait() 线程都唤醒。
notifyAll():所谓唤醒的意思就是让 线程池中的线程具备执行资格。
必须注意的是,这些方法都是在同步中才有效。同时这些方法在使用时必须标明所属 锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。
查看 JavaAPI 之后,发现这些方法 并不定义在 Thread 中,也没定义在 Runnable 接口中,却被定义在了 Object 类中 因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。
能被任意对象调用的方法一定定义在 Object 类中。
下面代码,模拟等待唤醒机制的实现:
class Resource2{
private String productName;
private int count = 1;
private boolean flag = false; // 资源类增加一个标志位,默认 false, 也就是没有资源
public synchronized void produce(String name){
if (flag == true) {//如果 flag 为 true,也就是有资源了,生产者线 程就去等待。
try {
wait(); // wait 函数抛出的异常只能被截获
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.productName=name+count;
count++;
System.out.println(Thread.currentThread().getName()+”…生产者+this.productName);
flag = true; // 生产完了就将 flag 修改为
true notifyAll(); // 然后唤醒其他线程
}
public synchronized void consume() {
if (flag == false) {// 如果 flag 为 false,也就是没有资源,消费 者线程就去等待
try {
wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"…消费 者…"+this.productName);
flag = false; // 消费完了就把标志改为
false notifyAll(); // 然后唤醒其他线程,因为有多个生产者和消费者线程, 所以要用 notifyAll, // 因为 notify 只唤醒一个,唤醒到同类型的线程就不好了。
}
} 输入线程任务类
public class Producer2 implements Runnable{
private Resource2 res; //生产者初始化就要分配资源
public Producer2(Resource2 res) {
this.res = res;
}
@Override public void run() {
for (int i = 0; i < 5; i++) {
res.produce(“bread”); //调用生成方法
}
}
} 输出线程任务类
package com.gx.demo; public class Comsumer2 implements Runnable{
private Resource2 res;//同理,消费者一初始化也要分配资源
public Comsumer2(Resource2 res){
this.res = res;
}
@Override public void run() {
for (int i = 0; i < 5; i++) {
res.consume(); //调用消费方法
}
}
} 测试类
public class ProducerAndConsumer2 {
public static void main(String[] args) {
Resource2 resource = new Resource2(); // 实例化资源
Producer2 producer = new Producer2(resource);// 实例化生产者, 并传入资源对象
Comsumer2 comsumer = new Comsumer2(resource);// 实例化消费者, 并传入相同的资源对象
Thread threadProducer1 = new Thread(producer); // 创建 2 个生 产者线程
Thread threadProducer2 = new Thread(producer);
Thread threadComsumer1 = new Thread(comsumer); // 创建 2 个消 费者线程
Thread threadComsumer2 = new Thread(comsumer);
threadProducer1.start();
threadProducer2.start();
threadComsumer1.start();
threadComsumer2.start();
}
}
线程 0 和 1 是生产者线程,他们每次只有一个进行生产。线程 2 和 3 是消费者线 程,同样的,每次只有一个进行消费。 上述代码中的问题有 2 点需要注意,第一点是用 if 还是 while 来判断 flag,第二点是用 notify 还是 notifyAll 函数。统一来说,while 判断在线程唤醒后还会再次判断,如果 只有一个生产者和消费者线程的话可以用 if,如果有多个生产者或者消费者,就必须用 while 判断,不然会出现死锁。 所以,最终要用 while 和 notifyAll()的组合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值