并发编程之CountDownLatch

时间:2023-02-09 20:48:12

  在前面的两篇文章中我们分别用volatile、notify()和wait()分别实现了一个场景,我们再来回顾一下前面的场景:在main方法中开启两个线程,其中一个线程t1往list里循环添加元素,另一个线程t2监听list中的size,当size等于5时,t2线程结束,t1线程继续执行,直到循环结束。看过上篇文章的应该知道上篇文章我们是用notify()和wait()配合来实现线程之间的交互的,但是这种方法不是很好理解,而且写起来比较麻烦,在notify()之后必须要wait()才能立即释放锁,而且wait()方法执行之前必须是要先获得锁的,这就意味着wait()方法必须在synchronized方法或者是synchronized代码块之中来执行,这并不是很方便,本文中我们将用另一种更为简单且容易理解的方式来实现这个场景,下面直接看代码:

 1 package com.fanjf.thread;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.concurrent.CountDownLatch;
 6 import java.util.concurrent.TimeUnit;
 7 
 8 public class Mycontainer3 {
 9     static List<Integer> integers = new ArrayList<>();
10     final static Object object = new Object();
11     static CountDownLatch latch = new CountDownLatch(1);
12     
13     public static void main(String[] args) {
14         new Thread(new Runnable() {
15             public void run() {
16                 System.out.println("t1启动");
17                 try {
18                     TimeUnit.SECONDS.sleep(1);
19                 } catch (InterruptedException e1) {
20                     e1.printStackTrace();
21                 }
22                     for(int i=0;i<10;i++){
23                         integers.add(i);
24                         if(integers.size()==5){
25                             latch.countDown();
26                         }    
27                         try {
28                             Thread.sleep(1000);
29                         } catch (InterruptedException e) {
30                             e.printStackTrace();
31                         }
32                         System.out.println("add:"+i);
33                     
34                     
35                 }
36                 System.out.println("t1结束");
37                 
38             }
39         }).start();
40         
41         new Thread(new Runnable() {
42             public void run() {
43                 System.out.println("t2启动");
44                 try {
45                     latch.await();
46                 } catch (InterruptedException e) {
47                     e.printStackTrace();
48                 }
49                 System.out.println("t2结束");
50                 
51                 
52             }
53             
54         }).start();
55     }
56 
57 }

执行结果如下:

 1 t1启动
 2 t2启动
 3 add:0
 4 add:1
 5 add:2
 6 add:3
 7 t2结束
 8 add:4
 9 add:5
10 add:6
11 add:7
12 add:8
13 add:9
14 t1结束

  很明显,这个结果跟我们的描述是一致的,现在来解释一下代码的意思,java并发包中为我们提供了一个CountDownLatch类,这个类的构造方法中可以传一个int值,首先线程t2执行await()方法,线程t1执行add操作,当size等于5时执行countDown(),这个countDown()会把传入的int值减1,只有当这个值减为0时,t2线程才能执行,所以当size等于5时此时值会减为0,t2就会继续执行了。