JUC系列04-CountDownLatch闭锁
2019-03-29 本文已影响0人
码蜂窝
1 为什么要使用CountDownLatch
先通过以下例子了解CountDownLatch到作用
package com.mafgwo.juc.testvolatile;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* CountDownLatch使用例子
*/
public class TestCountDownLatch {
public static void main(String[] args) {
// 开10个线程打印线程名
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
// 睡眠随机500ms内
try {
Thread.sleep(new Random().nextInt(500));
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}).start();
}
try {
countDownLatch.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印所有线程已处理完
System.out.println("所有线程已完成");
}
}
其他方式实现线程等待如下
package com.mafgwo.juc.testvolatile;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* 等待线程执行完到其他例子
*/
public class TestWaitThread {
public static void main(String[] args) {
List<Thread> threads = new ArrayList<>();
// 开10个线程打印线程名
for (int i = 0; i < 10; i++) {
Thread t = new Thread(() -> {
// 睡眠随机500ms内
try {
Thread.sleep(new Random().nextInt(500));
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
});
threads.add(t);
t.start();
}
for (Thread thread : threads) {
try {
thread.join(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 打印所有线程已处理完
System.out.println("所有线程已完成");
}
}
使用分析
两者的共同点
:都能做到等待全部线程执行完再执行主线程。
两者的区别
:CountDownLatch是使用计数方式,await阻塞主线程,当计数为0则继续执行。Thread.join则会不断检查线程是否存在,存活则调用wait方法阻塞线程,等待线程结束时的notifyAll。
总结
:CountDownLatch主要是用于多线程时需要完成某些线程,再继续往下执行的场景,不需要等待线程关闭,便于在线程池中使用。
注意事项
:第一,CountDownLatch.countDown()方法要放在finally中,避免程序异常未执行减1操作导致不必要的阻塞;第二,CountDownLatch.await方法要设置超时时间,避免某些异常场景下出现死锁。