Java中对线程的阻塞和唤醒有两种机制
一、通过Object的wait和notify结合synchronized关键字实现
二、Condition集合Lock
本文介绍第二种
Condition特性
- 类似于Object的wait和notify机制,但不同在于,Condition是需要关联Lock对象,通过Lock对象的newCondition()创建
- 可精细控制多线程,同一个锁,可以创建多个Condition
例如:多线程读/写一块堆内存缓存区,生成者消费者模式,通过Condition可以明确唤醒哪个线程
例子
package com.darchrow.test.condition; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 例子说明: * add()方法:当集合长度为10时,就挂起当前的线程, 让其他线程先走。否则就会添加一条信息,然后唤起执行sub()的线程 * sub()方法:当长度为0时,同理操作 * * @author mdl * @date 2020/3/25 10:08 */ public class ConditionDemo implements Runnable { private final static Lock lock = new ReentrantLock(); private final static Condition addCondition = lock.newCondition(); private final static Condition subCondition = lock.newCondition(); private static int num = 0; private static List<String> list = new LinkedList<>(); private boolean flag; private CountDownLatch countDwonLatch; public ConditionDemo(boolean flag, CountDownLatch countDwonLatch) { this.flag = flag; this.countDwonLatch = countDwonLatch; } private void add() { lock.lock(); try { if (list.size() == 10) { // 集合满了,不能再加了,等待减 addCondition.await(); } // 没满,可以继续添加元素 num++; list.add("add banana" + num); System.out.println("当前线程:" + Thread.currentThread().getName() + ", 向集合里加入元素, 目前长度" + list.size()); // 加完了,可以减了 subCondition.signal(); countDwonLatch.countDown(); System.out.println("当前线程:" + Thread.currentThread().getName() + "countDownLatch.getCount()=" + countDwonLatch.getCount()); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } private void sub() { lock.lock(); try { if (list.size() == 0) { // 集合空了,阻塞,不能再减了,等待 subCondition.await(); } // 有数据了,可以减 num--; String str = list.get(0); list.remove(0); System.out.println("当前线程:" + Thread.currentThread().getName() + ", 集合减元素, " + str + ",减少后长度" + list.size()); // 减完了,可以继续加了 addCondition.signal(); countDwonLatch.countDown(); System.out.println("当前线程:" + Thread.currentThread().getName() + "countDownLatch.getCount()=" + countDwonLatch.getCount()); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) throws InterruptedException { CountDownLatch countDwonLatch = new CountDownLatch(40); ConditionDemo ConditionDemo1 = new ConditionDemo(true, countDwonLatch); ConditionDemo ConditionDemo2 = new ConditionDemo(false, countDwonLatch); ExecutorService executorService1 = Executors.newFixedThreadPool(10); ExecutorService executorService2 = Executors.newFixedThreadPool(10); for (int i = 0; i < 20; i++) { executorService1.execute(ConditionDemo1); executorService2.execute(ConditionDemo2); } countDwonLatch.await(); executorService1.shutdown(); executorService2.shutdown(); System.out.println("最终集合元素个数:" + list.size()); // Thread t1 = new Thread(ConditionDemo1); // Thread t2 = new Thread(ConditionDemo1); // Thread t3 = new Thread(ConditionDemo1); // Thread t4 = new Thread(ConditionDemo1); // Thread t5 = new Thread(ConditionDemo1); // // Thread t6 = new Thread(ConditionDemo2); // Thread t7 = new Thread(ConditionDemo2); // Thread t8 = new Thread(ConditionDemo2); // Thread t9 = new Thread(ConditionDemo2); // // t1.start(); // t2.start(); // t3.start(); // t4.start(); // t5.start(); // t6.start(); // t7.start(); // t8.start(); // t9.start(); } @Override public void run() { if (flag) { add(); } else { sub(); } } }