博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(二)线程同步_7---在一个锁中使用多个条件(Condition)
阅读量:6474 次
发布时间:2019-06-23

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

hot3.png

在一个锁中使用多个条件(Using multiple conditions in a Lock)

一个Lock可能关联着一个或者多个条件,这些条件表现在Condition接口。这些条件(conditions)的目的是允许多个线程控制一个锁对象并且检查一个条件是真还是假,当一个条件为false时,那么线程将会被挂起,直到其他线程唤醒它;Condition接口提供了挂起一个线程和唤醒一个线程的机制;

在之前的生产者消费者例子中,使用了Lock来同步临界区,生产者和消费者都只有一个线程;在下面的例子中,生产者和消费者都将有多个线程,当缓冲区满时,所有的生产者将会被挂起,消费者负责唤醒生产者;当缓冲区空时,消费者将被挂起,生茶者负责唤醒消费者;

动手实现

(1)创建一个大小固定的队列作为生产者和消费者的缓冲区;

public class MyQueue
{ private ReentrantLock lock=new ReentrantLock(); private Condition pullConditon=lock.newCondition(); private Condition pushCondition=lock.newCondition(); private int maxSize; private LinkedList
list=new LinkedList<>(); public MyQueue(int size) { maxSize=size; } public void push(T t){ lock.lock(); try { while (list.size()== maxSize) { // Current push thread release lock and sleep. pushCondition.await(); } list.push(t); System.out.printf("%s Push Size %d\n", Thread.currentThread().getName(), list.size()); // Week up all pull thread pullConditon.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public T pull(){ T t=null; lock.lock(); try { while (list.size() == 0) { // Current poll thread release lock and sleep. pullConditon.await(); } t=list.poll(); System.out.printf("%s Pull Size %d\n", Thread.currentThread().getName(), list.size()); //Week up all push threads pushCondition.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } return t; }}
(2)创建消费者

public class Consumer implements Runnable{    private MyQueue
myQueue; public Consumer(MyQueue
myQueue) { this.myQueue = myQueue; } @Override public void run() { for (int i = 0; i < 50; i++) { myQueue.pull(); try { Random random=new Random(); Thread.sleep(random.nextInt(500)); } catch (InterruptedException e) { e.printStackTrace(); } } }}
(3)创建生产者

public class Producer implements Runnable{    private MyQueue
myQueue; public Producer(MyQueue
myQueue) { this.myQueue = myQueue; } @Override public void run() { for (int i = 0; i < 50; i++) { myQueue.push(i); try { Random random=new Random(); Thread.sleep(random.nextInt(500)); } catch (InterruptedException e) { e.printStackTrace(); } } }}
(4)Main,创建3个消费者,3个生产者

public class Main {    public static void main(String[] args) {        MyQueue
myQueue = new MyQueue<>(100); Thread[] producer = new Thread[3]; Thread[] consumer = new Thread[3]; for (int i=0;i
由于生产者和消费者一样多,生产者生产的和消费者消费的刚好,所以最终程序会正常结束;

要点

在该例子中,当一个生产者线程占用了锁对象,那么其他的生产者线程和消费者线程都将被挂起,直到该线程释放了锁对象;当队列满时,生产者将执行pushConditon接口的await()方法,执行该方法,该线程将会被挂起,并且同时释放掉锁对象,从而允许其它线程执行;到消费者执行pushConditon的signalAll()方法时(注意这里是signalAll()而不是notifyAll()),将会唤醒被所有被pushCondtion挂起的线程,即唤醒生产者;从这个例子生越来越感觉Java线程机制的强大和灵活;

转载于:https://my.oschina.net/u/1387007/blog/343261

你可能感兴趣的文章
ARP
查看>>
java mkdir()和mkdirs()区别
查看>>
桌面支持--excel自动换行
查看>>
虚拟化--003 vcac licence -成功案例
查看>>
windows server 2003各版本及2008各版本的最大识别内存大小
查看>>
OSChina 周六乱弹 ——揭秘后羿怎么死的
查看>>
centos查找未挂载磁盘格式化并挂载
查看>>
IT人员的职业生涯规划
查看>>
sorry,you must have a tty to run sudo
查看>>
ios开发中使用正则表达式识别处理字符串中的URL
查看>>
项目中的积累,及常见小问题
查看>>
Python类型转换、数值操作(收藏)
查看>>
注释书写格式
查看>>
SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别
查看>>
2013=7=30 自增量的浅谈
查看>>
oracle11g dataguard 安装手册(转)
查看>>
java并发包分析之———Deque和LinkedBlockingDeque
查看>>
1. Two Sum - Easy - Leetcode解题报告
查看>>
SQLiteHelper
查看>>
多线程---同步函数的锁是this(转载)
查看>>