1、CountDownLatch
功能:用于一个或多个线程等待其他线程完成操作,类似于join()。
原理:构造函数CountDownLatch(int N)接收一个int类型的参数N作为计数器,N可以是N个线程,也可以是一个线程里的N个步骤。调用一次countDown(),N减一;调用await(),阻塞当前线程。当N为零时,阻塞实效。
join()
功能:用于让当前线程等待join线程执行结束。
原理:不停检查join线程是否存活,如果join存活则让当前线程永远等待。直到join线程终止后,线程的this.notifyAll()方法会被调用,激活正在等待的线程。
public class JavaCountDownLatch {
private CountDownLatch countDownLatch
= new CountDownLatch(2);
@Test
public void test() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(1);
countDownLatch.countDown();
System.out.println(2);
countDownLatch.countDown();
}
}).start();
countDownLatch.await();
System.out.println(3);
}
}
未调用countDown时,输出:
1
2
并且当前线程永远等待。
调用countDown后,输出:
1
2
3
2、CyclicBarrier
功能:让一组线程到达一个屏障时阻塞,直到最后一个线程到达屏障时,屏障才会打开,所有阻塞的线程才会继续运行。
public class JavaCyclicBarrier {
private CyclicBarrier barrier = new CyclicBarrier(2, new A());
public static class A implements Runnable {
@Override
public void run() {
System.out.println(3);
}
}
@Test
public void test() {
new Thread(new Runnable() {
@Override
public void run() {
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(1);
}
}).start();
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(2);
}
}
输出:
3
1
2
构造函数CyclicBarrier(2,new A ()),定义阻塞两个线程,包括线程A,当线程都到达屏障时,优先执行线程A。
3、Semaphore
功能:控制同时访问特定资源的线程数量,即控制并发数量。
public class JavaSemaphore {
private static final int THREAD_COUNT = 30;
private static ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
private Semaphore semaphore = new Semaphore(10);
@Test
public void test() {
for (int i = 0; i < THREAD_COUNT; i++) {
service.execute(new Runnable() {
@Override
public void run() {
try {
// 获取许可证
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " save data");
// 释放许可证
semaphore.release();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
service.shutdown();
}
}
构造函数Semaphore(10)即允许10个线程并发。
4、Exchanger
功能:提供一个同步点,在这个同步点,两个线程可以交换数据。
原理:当第一个线程先执行exchange()方法,它会一直等待第二个线程执行exchange()方法,当两个线程到达同步点时,两个线程可以交换数据
public class JavaExchanger {
private Exchanger<String> exchanger = new Exchanger<>();
private ExecutorService service = Executors.newFixedThreadPool(2);
@Test
public void test() {
service.execute(new Runnable() {
@Override
public void run() {
try {
String A = "银行流水A";
String exhrA = exchanger.exchange(A);
System.out.println("A得到B的数据: " + exhrA);
} catch (Exception e) {
// TODO: handle exception
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
String B = "银行流水B";
String exhrB = exchanger.exchange(B);
System.out.println("B得到A的数据:" + exhrB);
} catch (Exception e) {
// TODO: handle exception
}
}
});
service.shutdown();
}
}
输出:
B得到A的数据:银行流水A
A得到B的数据: 银行流水B