1.闭锁
闭锁(latch)是一种Synchronizer,它可以延迟线程的进度直到线程打到终止状态。一个闭锁工作起来就像一道大门:直到闭锁达到终点状态之前,门一直是关着的,没有线程能够通过,在终点状态到来的时候,门开了,允许所有线程通过。一旦闭锁达到了终点状态,它就不能改变状态了,所以它会永远保持敞开状态。闭锁可以用来确保特定活动直道其他活动完成后发生。(引用 java并发编程实践)
2.CountDownLatch
CountDownLatch是一个灵活的闭锁的实现,允许一个任务等待其他任务执行完毕后才能执行,闭锁的状态包括一个计数器,用来表现需要等待的任务数。countDown方法对计数器做减操作,表示一个事件的已经发生,而await方法等待计数器打到零,此时所有需要等待的事件都已经发生,如果计数器入口值为非零,await会一直阻塞到计数器为零,或者等待线程中断或超时。
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class DemoCDL {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
CountDownLatch downLatch = new CountDownLatch(3);
Student s1 = new Student(downLatch, "no1");
Student s2 = new Student(downLatch, "no2");
Student s3 = new Student(downLatch, "no3");
Teacher t = new Teacher(downLatch);
service.execute(t);
service.execute(s1);
service.execute(s2);
service.execute(s3);
}
}
class Teacher implements Runnable{
private CountDownLatch downLatch;
public Teacher(CountDownLatch downLatch) {
this.downLatch = downLatch;
}
@Override
public void run() {
System.out.println("老师等待学生全部交完试卷");
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有学生交完试卷,考试结束");
}
}
class Student implements Runnable{
private CountDownLatch downLatch;
private String name;
public Student(CountDownLatch downLatch, String name) {
this.downLatch = downLatch;
this.name = name;
}
@Override
public void run() {
System.out.println(name + " 开始答卷");
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(10)); //假设学生在随机数内就答完卷
System.out.println(name + "答完卷上交试卷");
downLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果:
老师等待学生全部交完试卷
no1 开始答卷
no2 开始答卷
no3 开始答卷
no1答完卷上交试卷
no2答完卷上交试卷
no3答完卷上交试卷
所有学生交完试卷,考试结束
3.CyclicBarrier
CyclicBarrier与CountDownLatch相似,jdk解释A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.意思可以实现让一组线程等待至某个状态之后在全部同时执行。
CyclicBarrier的2个构造函数:
CyclicBarrier(int parties);
CyclicBarrier(int parties, Runnable barrierAction);barrierAction即为当这些线程都达到barrier状态时会执行的内容。
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class DemoCB {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable(){
@Override
public void run() {
System.out.println("在所有线程达到barrier状态执行内容");
}
});
ExecutorService service = Executors.newCachedThreadPool();
Worker w1 = new Worker(cyclicBarrier, "w1");
Worker w2 = new Worker(cyclicBarrier, "w2");
Worker w3 = new Worker(cyclicBarrier, "w3");
service.execute(w1);
service.execute(w2);
service.execute(w3);
}
}
class Worker implements Runnable{
private CyclicBarrier cyclicBarrier;
private String name;
public Worker(CyclicBarrier cyclicBarrier, String name) {
this.cyclicBarrier = cyclicBarrier;
this.name = name;
}
@Override
public void run() {
try {
System.out.println(name +" 等待执行");
TimeUnit.SECONDS.sleep(new Random().nextInt(10));
//等待所有线程打到barrier状态
cyclicBarrier.await();
System.out.println(name + " 开始工作");
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
执行结果
w2 等待执行
w1 等待执行
w3 等待执行
在所有线程达到barrier状态执行内容
w1 开始工作
w3 开始工作
w2 开始工作