这三个类都在java.util.concurrent包下面
-
CountDownLatch:允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。就是一个减法计数器
countDownLatch.countDown();//数量减一
countDownLatch.await();//等待计数器归零,然后再向下执行
原理:每次有线程调用countDown()数量减一,假设计数器变为0,await()方法就结束,就会被唤醒,继续执行之后的代码
-
CyclicBarrier:允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。就是一个加法计数器。
-
Semaphore:一个计数信号量。 在概念上,信号量维持一组许可证。 如果有必要,每个
acquire()
都会阻塞,直到许可证可用,然后才能使用它。 每个release()
添加许可证,潜在地释放阻塞获取方。 但是,没有使用实际的许可证对象;Semaphore
只保留可用数量的计数,并相应地执行。
acquire()得到 假设如果已经满了,等待,等待被释放为止
release()释放 释放,会将当前的信号量释放+1,然后唤醒等待的线程
作用:多个共享资源互斥!并发限流,控制最大的线程数
下面分别是这三个辅助类的简单实现:
package cn.itcast.thread;
import java.util.concurrent.CountDownLatch;
//减法计数器,6个线程跑完了才关门
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//总数是6,有一个方法,让它倒计时,方法就是countDown
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i=1;i<=6;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"GO OUT");
countDownLatch.countDown();//数量减一
},String.valueOf(i)).start();
}
countDownLatch.await();//等待计数器归零,然后再向下执行
System.out.println("关门");
}
}
package cn.itcast.thread;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
//集齐7颗龙珠召唤神龙
public static void main(String[] args) {
//召唤龙珠的线程
CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{
System.out.println("召唤神龙成功");
});
for (int i=1;i<=7;i++){
final int temp=i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"收集"+temp+"个龙珠");
try {
cyclicBarrier.await();//等待计数器变成7,继续向下执行
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
package cn.itcast.thread;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
public static void main(String[] args) {
//线程数量:停车位!限流
Semaphore semaphore=new Semaphore(3);
for (int i=1;i<=6;i++){
new Thread(()->{
//acquire()得到
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
//release()释放
}).start();
}
}
}