解题:Leetcode1115题:多线程交替打印问题
< 返回列表时间: 2020-07-14来源:OSCHINA
1.使用线程组同步工具SynchronousQueue实现交替打印 class FooBar { private int n; private SynchronousQueue fooTobar; private SynchronousQueue barTofoo; public FooBar(int n) { this.n = n; fooTobar = new SynchronousQueue(); barTofoo = new SynchronousQueue(); } public void foo(Runnable printFoo) throws InterruptedException { for (int i = 0; i < n; i++) { printFoo.run(); fooTobar.put(1); barTofoo.take(); } } public void bar(Runnable printBar) throws InterruptedException { for (int i = 0; i < n; i++) { fooTobar.take(); printBar.run(); barTofoo.put(1); } } }
思路:定义两个同步队列,分别代表foo到bar的消息流,和bar到foo的消息流。在每一轮循环,foo端,先打印,然后向bar端阻塞发送消息阻塞直到bar消费了消息,然后阻塞等待来自bar的消息,收到来自bar的消息后进入下一轮循环;在bar端,首先要阻塞接受来自foo的消息,直到收到了foo的消息,才能执行打印操作,完成打印后,向foo端阻塞发送消息,成功发送消息之后,bar端进入下一轮循环;
2.利用线程组同步工具信号量Semaphore实现交替打印 class FooBar { private int n; private Semaphore fooPrint; private Semaphore barPrint; public FooBar(int n) { this.n = n; fooPrint = new Semaphore(1); barPrint = new Semaphore(0); } public void foo(Runnable printFoo) throws InterruptedException { for (int i = 0; i < n; i++) { fooPrint.acquire(); printFoo.run(); barPrint.release(); } } public void bar(Runnable printBar) throws InterruptedException { for (int i = 0; i < n; i++) { barPrint.acquire(); printBar.run(); fooPrint.release(); } } }
思路:一个信号量(Semaphore)管理许多的许可证(permit)。 为了通过信号量,线程通过调用acquire 请求许可。其实没有实际的许可对象, 信号量仅维护一个计数。许可的数目是固定的, 由此限制了通过的线程数量。其他线程可以通过调用 release 释放许可。而且,许可不是必须由获取它的线程释放。事实上,任何线程都可以释放任意数目的许可,这可能会增加许可数目以至于超出初始数目。本题中维护两个信号量实例,fooPrint和barPrint,其中fooPrint初始化为1个许可,barPrint初始化为0个许可。在foo函数中首先需要获取一个fooPrint的许可才能打印,打印结束后,给barPrint增加一个许可,这个时候fooPrint中没有任何许可barPrint中有一个许可,然后foo进入下一轮循环,但是无法获取许可,会阻塞等待上一轮bar函数执行完;在bar函数中首先需要获取一个barPrint的许可才能打印,打印结束后,给fooPrint增加一个许可,这个时候barPrint中没有任何许可fooPrint中有一个许可,然后bar进入下一轮循环,但是无法获取许可,会阻塞等待上本轮foo函数先执行完;
热门排行