Java精通并发-通过Condition实现线程间通信实例剖析【下】

在上一次https://www.cnblogs.com/webor2006/p/12083720.html完成了Condition线程同步的实例,但是还木有对其运行流程进行分析,所以这次对它进行一个细致的分析,并且再对其代码做一些调整加深对其的印象,先回顾一下上次的代码:

public class MyTest2 {
    public static void main(String[] args) {
        BoundedContainer boundedContainer = new BoundedContainer();

        //利用java8的流来产生多个生产者线程
        IntStream.range(0, 10).forEach(i -> new Thread(() -> {
            try {
                boundedContainer.put("hello");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start());
        //利用java8的流来产生多个生产者线程
        IntStream.range(0, 10).forEach(i -> new Thread(() -> {
            try {
                boundedContainer.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start());
    }
}

class BoundedContainer {
    private String[] elements = new String[10];
    private Lock lock = new ReentrantLock();
    private Condition notEmptyCondition = lock.newCondition();
    private Condition notFullCondition = lock.newCondition();
    private int elementCount;//elements数组中已有的元素数量
    private int putIndex;
    private int takeIndex;

    public void put(String element) throws InterruptedException {
        this.lock.lock();
        try {
            while (this.elementCount == this.elements.length) {
                notFullCondition.await();
            }

            elements[putIndex] = element;
            if (++putIndex == this.elements.length) {
                putIndex = 0;
            }
            ++elementCount;
            System.out.println("put method: " + Arrays.toString(elements));

            notEmptyCondition.signal();

        } finally {
            this.lock.unlock();
        }
    }

    public String take() throws InterruptedException {
        this.lock.lock();

        try {
            while (0 == this.elementCount) {
                notEmptyCondition.await();
            }
            String element = elements[takeIndex];
            elements[takeIndex] = null;

            if (++takeIndex == elements.length) {
                takeIndex = 0;
            }

            --elementCount;
            System.out.println("take method: " + Arrays.toString(elements));

            notFullCondition.signal();

            return element;

        } finally {
            this.lock.unlock();
        }
    }
}

其运行结果如下:

所以在结果的输出上也存在一个先后顺序了,先打印的是存放相关的输出,再打印的取元素,如下:

而从输出的结果可以看到,存放元素的位置和取出元素的位置如预期,都是按着上一次的位置进行的,那如果咱们这样巅倒一下顺序呢?

 

再运行:

这次的输出就木有这么工整了,原因是由于在还木有元素的情况下先消费肯定会阻塞,所以:

接着就不继续细分析了,基本上就是按着上面说的原则进行执行的,好,下面继续来修改一下生产者与消费者的线程数,来对写的程序做做测试:

嗯,没啥问题,先生产了5个数据,然后再消费了5个,接下来再来修改:

结果:

put method: [hello, null, null, null, null, null, null, null, null, null]
put method: [hello, hello, null, null, null, null, null, null, null, null]
put method: [hello, hello, hello, null, null, null, null, null, null, null]
put method: [hello, hello, hello, hello, null, null, null, null, null, null]
put method: [hello, hello, hello, hello, hello, null, null, null, null, null]
put method: [hello, hello, hello, hello, hello, hello, null, null, null, null]
put method: [hello, hello, hello, hello, hello, hello, hello, null, null, null]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, null, null]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, null]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [null, hello, hello, hello, hello, hello, hello, hello, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, null, hello, hello, hello, hello, hello, hello, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, null, hello, hello, hello, hello, hello, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, null, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, null, null, hello, hello, hello, hello, hello]
put method: [hello, hello, hello, hello, null, hello, hello, hello, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, hello, hello, null, hello, hello, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, hello, hello, hello, null, hello, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, hello, hello, hello, hello, null, hello, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, hello, hello, hello, hello, hello, null, hello]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, null]
put method: [hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [null, hello, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [null, null, hello, hello, hello, hello, hello, hello, hello, hello]
take method: [null, null, null, hello, hello, hello, hello, hello, hello, hello]
take method: [null, null, null, null, hello, hello, hello, hello, hello, hello]
take method: [null, null, null, null, null, hello, hello, hello, hello, hello]
take method: [null, null, null, null, null, null, hello, hello, hello, hello]
take method: [null, null, null, null, null, null, null, hello, hello, hello]
take method: [null, null, null, null, null, null, null, null, hello, hello]
take method: [null, null, null, null, null, null, null, null, null, hello]
take method: [null, null, null, null, null, null, null, null, null, null]

Process finished with exit code 0

20个生产者与20个消费者执行完之后,最终肯定是把数组中的元素都给消费掉了,妥妥的。继续来修改程序进行测试:

那如果反过来呢?

运行:

以上就是关于Condition这个例子解析,说实话要实现这样一个功能并不是很简单的,但是消化好这个例子对于Condition的理解是非常好的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

webor2006

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值