Latch:门闩。一种线程通信的方式;当程序不涉及同步,仅仅需要线程通信的时候,使用synchronize或者lock的线程通信等待唤醒机制,就显得太重了;
这时候,可以考虑使用信号量类:CountDownLatch,cylicbarrier,semaphore
CountDownLatch是一个多线程控制工具类。可以实现计数器的功能。
CountDownLatch的两种应用场景:(不能实现多个线程顺序执行!)
1. 让某线程等待其他线程执行完毕,再开始执行;
2. 让多个线程同时开始并行执行;
构造器:
// 传入一个count,指定要等待的线程个数 public CountDownLatch(int count)
主要方法:
// 调用await的线程会被挂起,直到count==0,才会继续执行。 public void await(){}; // 等待一定时间,count还没有为0,线程继续执行 public boolean await(long timeout, TimeUnit unit){}; // 将count值减1,一般在线程执行结束,调用此方法,代表计数器减1. public void countDown() {};
第一种场景:
让某线程,等待n个线程执行结束,再继续执行;
创建一个Task类
public class Task implements Runnable { private String name; private CountDownLatch latch; // 线程需要CountDownLatch对象 public Task(CountDownLatch latch, String name) { this.latch = latch; this.name = name; } @Override public void run() { try { Thread.sleep(1000); System.out.println(this.name + " Over"); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); // 执行完毕,计数器减一 } } }
主方法:
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchTest { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(3); Task task_A = new Task(latch, "A"); Task task_B = new Task(latch, "B"); Task task_C = new Task(latch, "C"); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.submit(task_A); executorService.submit(task_B); executorService.submit(task_C); executorService.shutdown(); // 挂起mian线程,等待计数器置0,也就是三个线程执行完毕。 latch.await(); System.out.println(Thread.currentThread().getName()); } }
运行结果:
A Over B Over C Over main // 等待三个线程执行完毕,main线程执行
第二种场景:
其实跟第一种,基本一样,只不过反着来;await所有的用户线程,让main线程先行,计数器减一,为0;接着用户线程就会一起启动;
这个方式,对于并发其实没有什么用,主要用于并行的场景;真正的同时启动多个线程。