在上一次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的理解是非常好的。