前言:
现在兄弟们对“java线程的唤醒”大约比较重视,小伙伴们都想要知道一些“java线程的唤醒”的相关文章。那么小编在网上网罗了一些关于“java线程的唤醒””的相关知识,希望咱们能喜欢,朋友们一起来了解一下吧!先定义资源类 :包含资源数量,消费方法,生产方法
当资源为0时,生产者生产资源
当资源为1时,消费者消费资源
//定义Resource作为线程需要的资源public class Resource { //当前资源的数量 int num=0; //当前资源的上限 int size=1; //消费资源 public synchronized void remove(){ if(num==0){ try { System.out.println("消费者等待"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } num--; System.out.println("消费者线程为:"+Thread.currentThread().getName()+"资源数量"+num); notifyAll(); } //生产资源 public synchronized void put(){ if(num==size){ try { System.out.println("生产者等待"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } num++; System.out.println("生产者线程为:"+Thread.currentThread().getName()+"资源数量"+num); notifyAll(); }}复制代码
创建消费者线程
//定义Consumer使用remove消费资源public class Consumer implements Runnable { private Resource resource; public Consumer(Resource resource) { this.resource = resource; } @Override public void run() { for(int i=0;i<10;i++){ resource.remove(); } }}复制代码
创建生产者线程
//定义Producer使用put生产资源public class Producer implements Runnable { private Resource resource; public Producer(Resource resource) { this.resource = resource; } @Override public void run() { for(int i=0;i<10;i++){ resource.put(); } }}复制代码
执行线程
public static void main(String[] args) { Resource resource = new Resource(); Consumer consumer = new Consumer(resource); Producer producer = new Producer(resource); new Thread(consumer).start(); new Thread(producer).start();}复制代码
可以发现:线程执行情况正常
但是当我们分别有两个消费者和生产者时,线程执行就出现了异常
public static void main(String[] args) { Resource resource = new Resource(); Consumer consumer = new Consumer(resource); Producer producer = new Producer(resource); new Thread(producer,"生产者1").start(); new Thread(producer,"生产者2").start(); new Thread(consumer,"消费者1").start(); new Thread(consumer,"消费者2").start();}复制代码
这就是虚假唤醒问题
当我们的线程执行了start,此时线程都进入就绪状态
生产者1获取cpu执行权,变为运行状态,执行其中run方法,资源数+1
接着生产者1和生产者2先后获取cpu执行权,因为资源数为1,线程阻塞
消费者获取cpu执行权,资源数-1,并且会唤醒阻塞的线程
这时候就变成最初的状态
当生产者再次执行,是从刚才阻塞的地方继续运行,就不用再判断资源的数量是否为0了
出现虚假唤醒的原因是从阻塞态到就绪态再到运行态没有进行判断
我们可以每次得到操作权时都进行判断,将if判断改成while判断即可
此时执行情况正常
作者:十二时辰_
链接:
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
标签: #java线程的唤醒