简介
CountDownLatch像是一个计数器,适用于主线程要等待子线程执行完之后才继续执行的场景。它是不可重用的,每次使用只能重新构造。
常用方法
- CountDownLatch(int count) : 构造方法,入参指定线程控制量,即要等待几个子线程执行完毕(准确的说是要执行几次countDown使得count为0)之后等待线程才能继续执行
- void countDown():每次执行count减1,一般作为线程的最后一个步表示当前线程执行完毕
- void await():等待子线程执行完毕(count为0)。如果count不为0则一直等待下去直到count为0或线程被中断。
- boolean await(long timeout, TimeUnit unit):等待子线程执行完毕(count为0),参数为超时时间,即超过这个时间主线程不再等待,任由还没执行完毕的线程继续执行。其具有返回值。如果是count为0导致的等待结束返回true。超时导致的await结束返回false。
- long getCount():当前还在执行的线程数(count)
值得注意的是await是否继续等待的标准是count是否为0而不是子线程执行状态,子线程执行完毕必须主动调用countDown()才算CountDownLatch下一次有效的子线程执行。
示例
package sync;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
public class CountDownLatchTest {
public static void main(String[] args) {
final CountDownLatch cd= new CountDownLatch(2); // 要控制的线程数,即需要countDown的次数
Callable<String> c1 = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("This Is Callable1");
Thread.sleep(5000);
System.out.println("c.countDown");
cd.countDown(); // 初始count数减1
return "The ruturn of Callable1";
}
};
FutureTask<String> task1 = new FutureTask<>(c1);
final Thread t1 = new Thread(task1);
Callable<String> c2 = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("This Is Callable2");
cd.countDown();
System.out.println("cd count : " + cd.getCount()); // task1在等待,这里已经countDown,因此这里是1
Thread.sleep(1000);
System.out.println("中断task1");
t1.interrupt(); // 另一个线程中断await依然会等待下去
return "The return of Exception Callable2";
}
};
FutureTask<String> task2 = new FutureTask<>(c2);
try {
t1.start();
Thread.sleep(500); // 睡眠500保证task1进入sleep状态
new Thread(task2).start();
System.out.println("开始await");
long ts = System.currentTimeMillis();
System.out.println(cd.await(3, TimeUnit.SECONDS)); // 只有3个条件能使await停止等待:1.所控制线程执行完毕,即getCount等于0时
// 2.超时 3.主线程(await所在的线程)被结束,他所控制的线程如果在执行countDown之前被中断await也不会管,
// 他依然会等待下去(await只认countDown与超时,你是否被中断他不管),直到超时。
// count为0导致的等待结束返回true否则返回false
long te = System.currentTimeMillis();
System.out.println("等待时间:" + (te - ts));
System.out.println("END");
} catch (InterruptedException e) {
System.out.println("Exception");
}
}
}
运行结果:
This Is Callable1
开始await
This Is Callable2
cd count : 1
中断task1
false
等待时间:3003
END
PS:
【JAVA核心知识】系列导航 [持续更新中…]
上篇导航:14:JAVA线程池常用方法
下篇导航:15.2:线程控制器CyclicBarrier
欢迎关注…