CountDownLacth(倒计时闩):
个人理解:使用同一个CountDownLacth的多个线程,可以使用CountDownLacth提供的await方法,实现阻塞等待,
需要其他线程调用CountDownLacth提供的countDown方法来唤醒它,CountDownLacth有构造函数,如果传入2,那么
就要两个其他线程调用countDown方法来唤醒它。
场景:经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作。
public class UseCountDownLatch {
public static void main(String[] args) {
/**三个线程共用一个CountDownLatch **/
final CountDownLatch countDown = new CountDownLatch(2);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("进入线程t1" + "等待其他线程处理完成...");
/**
* 线程t1将进入等待,因为初始化传入参数2,所以要等待两个线程去唤醒他
*/
countDown.await();
System.out.println("t1线程继续执行...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("t2线程进行初始化操作...");
Thread.sleep(3000);
System.out.println("t2线程初始化完毕,通知t1线程继续...");
countDown.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("t3线程进行初始化操作...");
Thread.sleep(4000);
System.out.println("t3线程初始化完毕,通知t1线程继续...");
countDown.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t3.start();
}
}
进入线程t1等待其他线程处理完成...
t2线程进行初始化操作...
t3线程进行初始化操作...
t2线程初始化完毕,通知t1线程继续...
t3线程初始化完毕,通知t1线程继续...
t1线程继续执行...
CyclicBarrier(环屏障):
个人理解:使用同一个CyclicBarrier的多个线程,可以使用CyclicBarrier提供的await方法,实现所有的
线程阻塞,直到所有线程都运行了await方法,才统一执行下面的代码。
类似场景:
每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个人没有准备好,大家都等待。
public class UseCyclicBarrier {
/**
* 模拟运动员athlete
*/
static class Athlete implements Runnable {
/**初始化传进来的**/
private CyclicBarrier barrier;
private String name;
public Athlete(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(1000 * (new Random()).nextInt(5));
System.out.println(name + " 准备OK.");
//共用barrier的线程都执行到这里,才能执行下面的代码
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(name + " Go!!");
}
}
public static void main(String[] args) throws IOException, InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(3); // 3
ExecutorService executor = Executors.newFixedThreadPool(3);
/**
* 三个线程共工一个barrier
*/
executor.submit(new Thread(new Athlete(barrier, "zhangsan")));
executor.submit(new Thread(new Athlete(barrier, "lisi")));
executor.submit(new Thread(new Athlete(barrier, "wangwu")));
executor.shutdown();
}
}
wangwu 准备OK.
zhangsan 准备OK.
lisi 准备OK.
lisi Go!! //后面的一起打印
zhangsan Go!!
wangwu Go!!
Semaphore(信号量):
可以控制系统的流量:拿到信号量的线程可以进入,否则就等待。通过acquire()和release()获取和释放访问许可
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println("Accessing: " + NO);
//模拟实际业务逻辑
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(semp.getQueueLength());
// 退出线程池
exec.shutdown();
}