现实生活做中有很多这样的场景:做F前需要等待A,B,C,D,E完成,A,B,C,D,E可以并发完成,没有特定顺序,例如:周末在家里吃饭,有3件事情要做,爸爸做饭,妈妈做菜,儿子收拾餐桌,摆放碗筷。可以看到这个场景的特征为:
1.在吃饭前有N件事情要做,每件事情都做完后才能吃饭,待处理的事情为N,每做完一件待处理事情就减少1,当待处理事情为0时,就可以吃饭了。
2.每件事情可以并行处理,没有先后顺序,因而提高了效率。
围绕吃饭,整个过程如下:
在应用程序中处理并行操作时和上述场景类似,碰到这种场景时可以通过java并发工具CountDownLatch来实现。
代码类结构如下:
class EatingActivity implements Runnable { private CountDownLatch countDownLatch; public EatingActivity(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public void run() { try { //等待吃饭 System.out.println("Waiting for dinner..."); this.countDownLatch.await(); //所有事情做完后,await被唤醒,开始吃饭 System.out.println("Start eating..."); } catch (InterruptedException e) { e.printStackTrace(); } } } 复制代码
/** * 做饭 */ class MakeRice implements Runnable { private CountDownLatch countDownLatch; public MakeRice(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public void run() { exec(); } /** * 模拟做饭 */ private void exec() { try { System.out.println("Start making rice..."); long millis = ((int)(1+Math.random()*(5-1+1))) * 1000; Thread.sleep(millis); System.out.println("Making rice is finished."); //待处理事情减1 this.countDownLatch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } } 复制代码
/** * 做菜 */ class MakeDish implements Runnable { private CountDownLatch countDownLatch; public MakeDish(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public void run() { exec(); } /** * 模拟做菜 */ private void exec() { try { System.out.println("Start making dish..."); long millis = ((int)(1+Math.random()*(5-1+1))) * 1000; Thread.sleep(millis); System.out.println("Making dish is finished."); //待处理事情减1 this.countDownLatch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } } 复制代码
/** * 收拾桌子 */ class CleanUpTable implements Runnable { private CountDownLatch countDownLatch; public CleanUpTable(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public void run() { exec(); } /** * 模拟收拾桌子 */ private void exec() { try { System.out.println("Start making rice..."); long millis = ((int)(1+Math.random()*(5-1+1))) * 1000; Thread.sleep(millis); System.out.println("Cleaning up table is finished."); //待处理事情减1 this.countDownLatch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } } 复制代码
/** * @ClassName CountDownLatchTest * @Description 验证CountDownLatch * @Author 铿然一叶 * @Date 2019/10/7 22:32 * @Version 1.0 * javashizhan.com **/ public class CountDownLatchTest { public static void main(String[] args) { //为了吃饭,有3件事情要做 CountDownLatch countDownLatch = new CountDownLatch(3); //吃饭活动 Thread eatingActivity = new Thread(new EatingActivity(countDownLatch)); eatingActivity.start(); //做饭 Thread makeRice = new Thread(new MakeRice(countDownLatch)); //做菜 Thread makeDish = new Thread(new MakeDish(countDownLatch)); //收拾桌子 Thread cleanUpTable = new Thread(new CleanUpTable(countDownLatch)); //并行开始做事情 makeRice.start(); makeDish.start(); cleanUpTable.start(); } } 复制代码
输出日志:
Waiting for dinner... Start making rice... Start making rice... Start making dish... Cleaning up table is finished. Making rice is finished. Making dish is finished. Start eating... 复制代码
拼团场景中,满多少人后就可以成团,用到了计数器,看起来可以用CountDownLatch来实现,实际上没有必要,因为拼团可以不是并行的,只要有计数器就可以实现。