上一篇:多线程05--ReentrantLock 原理_fengxianaa的博客-CSDN博客
1. CountDownLatch
/**
* CountDownLatch
* 允许某个线程等待其他线程完成后再执行,工作中经常使用
*/
public class Lock04 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(5);
for(int i=0;i<5;i++){
new Thread(() ->{
try{
String name = Thread.currentThread().getName();
if("Thread-0".equals(name)){
System.out.println(name+"休息一下。。。");
Thread.sleep(3000);
}
System.out.println(name+"已经吃完饭。。。");
}catch (Exception e){
e.printStackTrace();
}finally {
// 最好是将这句代码放在 finally 中,防止因为异常导致无法countDown
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
System.out.println("都已经吃完饭。。。");
}
}
2. CyclicBarrier
/**
* CyclicBarrier
* 循环屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行
*
* CyclicBarrier(int parties)
* parties:表示需要拦截的线程数
*
* await()
* 如果当前线程不是最后一个线程,那么调用此方法会被阻塞。除非以下某个场景出现:
* 最后一个线程到达
* 某个线程中断当前线程 或 另一个等待线程
* 某个线程在等待 barrier 时超时
* 某个线程在此 barrier 上调用 reset()
*
* 如果当前线程,在进入此方法时已经被中断 或 在等待时被中断,抛:InterruptedException
* 如果线程在等待时被 中断,则其他等待线程都将抛出 BrokenBarrierException 异常,并将 barrier设为损坏状态
*/
public class Lock05 {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
Thread t0 = new Thread(() -> {
try {
String name = Thread.currentThread().getName();
System.out.println(name + "到了。。。");
cyclicBarrier.await();
System.out.println(name + "开始吃饭。。。");
} catch (Exception e) {
e.printStackTrace();
}
});
t0.start();
Thread.sleep(2000);
Thread t1 = new Thread(() -> {
try {
String name = Thread.currentThread().getName();
System.out.println(name + "到了。。。");
cyclicBarrier.await();
System.out.println(name + "开始吃饭。。。");
} catch (Exception e) {
e.printStackTrace();
}
});
t1.start();
// Thread.sleep(1000);
// t0.interrupt();
}
3. Semaphore
/**
* Semaphore
* 信号量,控制同时访问特定资源的线程数量
*
* Semaphore(int permits)
* 接受一个整型的数字,表示可用的许可证数量
*
* acquire()
* 阻塞当前线程,直到获取一个许可证,阻塞时,如果被 interrupt,抛:InterruptedException
*
* void release()
* * 释放一个许可,别忘了在finally中使用,注意:多次调用该方法,会使信号量的许可数增加,达到动态扩展的效果,如:初始permits为1, 调用了两次release,最大许可会改变为2
*
* void acquire(int permits)
* 获取指定数目的许可,如果无可用许可前也将会一直阻塞等待
*
* boolean tryAcquire()
* 从信号量尝试获取一个许可,如果无可用许可,直接返回false,不会阻塞
*
* boolean tryAcquire(int permits)
* 尝试获取指定数目的许可,如果无可用许可直接返回false
*
* boolean tryAcquire(int permits, long timeout, TimeUnit unit)
* 在指定的时间内尝试从信号量中获取许可,如果在指定的时间内获取成功,返回true,否则返回false
*
* int availablePermits()
* 获取当前信号量可用的许可
*/
public class Lock06 {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
Semaphore semaphore = new Semaphore(2);
for(int i=0;i<3;i++){
new Thread(() -> {
try {
semaphore.acquire();//获取许可证
String name = Thread.currentThread().getName();
System.out.println(name + "开始运行。。。");
} catch (Exception e) {
e.printStackTrace();
}finally {
semaphore.release();//释放许可证
}
}).start();
}
}
}