博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java学习之多生产者和多消费者
阅读量:4630 次
发布时间:2019-06-09

本文共 3752 字,大约阅读时间需要 12 分钟。

在上一节当中我们说道了,java多线程当中单个消费者对应单个生产者的关系。这个时候有几个点需要注意一下,第一个就是把if判断flag的语句改成while这样能够避免,比如如果我们这个时候用if的话判断完为真之后,线程就睡过去了,但是当下一次线程notify的时候,这个时候生产者还有消费者,也就是一个锁上面的线程拥有线程苏醒的机会是等同的。这个时候,如果生产者冻结之后,紧接着notify的话这个时候苏醒的还可能是生产者,这是我们不愿意看到的。那我们应该如何来处理呢,这个时候我们就应该把if改成while因为while是个循环,当下一次该线程苏醒的时候还应到回过头来判断,flag标记,这样就避免了生产者自我唤醒的这种情况。

但是现在问题变了,就是这个时候有多个生产者还有多个消费者,我们知道当只有一个生产者还有一个消费者的时候,至少会唤醒其中的一个,那么要是多个生产者还有多个消费者呢,我们可以这样想一下,比如说这个时候有两个生产者A和B,还有两个消费者C和D,此时A生产完了之后,这个时候A就开始唤醒了,假如A唤醒了C这个时候C开始生产消费产品,消费完了之后开始通知其他线程,这个时候假如被唤醒的是D线程,因为flag是假的证明已经没有东西可消费了,这个时候他又冻结。那么这个时候其他线程就都被冻结了,这个时候就形成了死锁现象,如果要避免死锁现象的话,java又为我们提供了一个方法,叫做notifyAll()方法,这个方法的作用在于能够把所有的线程都唤醒,这样就能保证消费者还有生产者至少可以唤醒双方的一个线程,保证程序的正常运行。这样做的一个缺点就是其中还有一个属于己方的线程被唤醒,这样就浪费了资源。于是在jdk更新的时候,就为我们提供了一个新的api能够显式的来操作锁还有唤醒冻结线程,这个线程不再核心lang包当中,这个apijava.util.concurrent.locks这个包当中为我们提供了两个接口,一是Lock接口还有一个是Condition接口。Lock接口扩展的方法有lock()方法还有一个unlock方法,这里需要注意的一点是,无论如何一定要释放锁,这个时候就用到了前面异常所讲到的finally语句,无论如何一定要执行。Lock当中还扩展了一个方法就是newCondition()这个方法,这个方法的作用是给一个锁定义多个消息传递的方式也就是给线程绑定多个监视器,比如说生产者只唤醒消费者的线程,而不唤醒生产者的线程,同理消费者也是如此。同时在Lock当中等待的方法不是wait()方法,唤醒的方法也不是notify()方法,这两个方法分别对应Lock当中的await()方法和signal()方法。

我们综合上面所讲来用代码体现下:

1 import java.util.concurrent.locks.*;  2 class KaoYa  3 {  4   5     int num = 1;  6   7     Lock l = new ReentrantLock();  8   9     Condition c1 = l.newCondition();  10     Condition c2 = l.newCondition();  11  12     boolean flag; 13  14     public void produce() throws InterruptedException 15     { 16             l.lock(); 17              18             try{ 19                 while(true) 20                 { 21                     while(flag) 22                         c1.await(); 23                         System.out.println(Thread.currentThread().getName()+"KaoYa...."+num); 24                         flag = true; 25                         c2.signal(); 26                 }        //num++; 27          28             }finally 29             { 30                 l.unlock(); 31             } 32     } 33  34     public void consume() throws InterruptedException 35     { 36         l.lock(); 37              38             try{ 39                 while(true) 40                 { 41                     while(!flag) 42                         c2.await(); 43                     System.out.println(Thread.currentThread().getName()+"KaoYa------"+num); 44                     num++; 45                     flag = false; 46                     c1.signal();     47                 }                 48             }finally 49             { 50  51                 l.unlock(); 52  53             } 54     } 55  56 } 57  58 class Product implements Runnable 59 { 60  61     KaoYa k; 62     Product(KaoYa k) 63     { 64  65         this.k = k; 66  67     } 68  69     public void run() 70     { 71         try{ 72             k.produce(); 73         }catch(InterruptedException e) 74         { 75  76         } 77     } 78 } 79  80  81 class Consume implements Runnable 82 { 83  84     KaoYa k; 85     Consume(KaoYa k) 86     { 87  88         this.k = k; 89  90     } 91  92     public void run() 93     { 94      95         try{ 96             k.consume(); 97         }catch(InterruptedException e) 98         { 99 100         }101             102 103     }104 105 106 }107 108 class LockDemo109 {110 111     public static void main(String[] args) {112         113         KaoYa k = new KaoYa();114         Product p = new Product(k);115         Consume c = new Consume(k);116 117         Thread t1 = new Thread(p);118         Thread t2 = new Thread(p);119         Thread t3 = new Thread(c);120         Thread t4 = new Thread(c);121 122 123         t1.start();124         t2.start();125         t3.start();126         t4.start();127 128     }129 130 }

转载于:https://www.cnblogs.com/sunchuanzhen/p/3381459.html

你可能感兴趣的文章
安装centos后无法引导启动windows7的解决方法
查看>>
AutoMapper用法
查看>>
Asterisk安装
查看>>
鄙视题
查看>>
如何在Vue项目中使用vw实现移动端适配(转)
查看>>
Apache Tomcat 7.x 概述
查看>>
as3绕过策略文件给视频截图
查看>>
C语言程序设计第一次作业
查看>>
leetcode网学习笔记(1)
查看>>
自制操作系统Antz(9)——实现内核 (下) 实现图形化界面
查看>>
JavaScript获取当前日期,昨天,今天日期以及任意天数间隔日期
查看>>
电子宠物系统
查看>>
windows远程桌面如果超出最大连接数, 使用命令行mstsc /console登录即可
查看>>
49. Group Anagrams
查看>>
SPOJ ATOMS - Atoms in the Lab
查看>>
关于 ListBox 自动换行
查看>>
postman测试上传文件
查看>>
R. ftp软件
查看>>
List<T>中,Remove和RemoveAt区别
查看>>
十月回家记
查看>>