并发编程-Condition

Condition

一个Lock中应该绑定一个Condition对象。Condition是Java提供用来实现等待/通知的类。
我们知道Object对象提供了wait、waitAll、notify、notifyAll的方法用来实现线程的同步、等待和唤醒。
但Condition类提供了比wait/notify更丰富的功能,Condition对象由lock对象所创建的,同时一个Lock可以创建多个Condition对象,即创建多个对象监听器,这样就可以指定唤醒具体线程,而notify是随机唤醒线程。

Condition接口

  • void await():造成当前线程在接到信号或被中断之前一直处于等待状态。
  • boolean await(long time, TimeUnit unit):造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
  • long awaitNanos(long nanosTimeout):造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
  • void awaitUninterruptibly():造成当前线程在接到信号之前一直处于等待状态。
  • boolean awaitUntil(Date deadline):造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
  • void signal():唤醒一个等待线程。

范例

public class Resource {
    private final int MAX_SIZE = 10;
    private List<Object> list = Lists.newArrayList();
    private Lock lock = new ReentrantLock();
    private Condition produceCondition = lock.newCondition();
    private Condition consumerCondition = lock.newCondition();

    public void produce() {
        while (true) {
            lock.lock();
            try {
                while (list.size() == MAX_SIZE) {
                    System.out.println("生产满了,暂时无法生产:" + list.size());
                    consumerCondition.signal();
                    try {
                        produceCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.add(new Object());
                System.out.println(Thread.currentThread().getName() + "生产新产品,共有:" + list.size());
            } finally {
                lock.unlock();
            }
        }
    }

    public void consume() {
        while (true) {
            lock.lock();
            try {
                while (CollectionUtils.isEmpty(list)) {
                    System.out.println("没有物品了,需要生产了");
                    produceCondition.signal();
                    try {
                        consumerCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "消费产品,共有:" + list.size());
                list.remove(0);
            } finally {
                lock.unlock();
            }
        }
    }

}

生产者线程

public class ProduceThread implements Runnable {

    private Resource resource;

    public ProduceThread(Resource resource){
        this.resource = resource;
    }

    @Override
    public void run() {
        resource.produce();
    }
}

消费者线程

public class ConsumerThread implements Runnable {

    private Resource resource;

    public ConsumerThread(Resource resource){
        this.resource = resource;
    }

    @Override
    public void run() {
        resource.consume();
    }
}

测试案例

public class ConditionDemo {
    public static void main(String[] args) throws InterruptedException {
        Resource resource = new Resource();
        ProduceThread produceThread = new ProduceThread(resource);
        ConsumerThread consumerThread = new ConsumerThread(resource);
        // 4个生产者
        for (int i = 0; i < 4; i++) {
            new Thread(produceThread).start();
            new Thread(consumerThread).start();
        }
    }
}
posted @   SpecialSpeculator  阅读(88)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示