Java Condition

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();
        }

    }
}

 

posted @ 2020-03-25 15:45  饮酒至天明  阅读(255)  评论(0编辑  收藏  举报