辅助类
JUC包下,三个辅助类, CountDownLatch, CyclicBarrier, Semaphore
CountDownLatch
作用:允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
首先看看这个辅助类,从英文字母上理解,这就是一个减法,
这个类只有一个有参构造器,就能得知,这就是个待减数值,根据官方的解释:CountDownLatch用给定的计数初始化。 await方法阻塞,直到由于countDown()方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的await 调用立即返回。
作用场景:
例: 一个CountDownLatch为一个计数的CountDownLatch用作一个简单的开/关锁存器,或者门:所有线程调用await在门口等待,直到被调用countDown()的线程打开。
看看他的方法
我们可以很清楚的字知道这个类的用法
下面是我的实例代码
public static void main(String[] args) throws InterruptedException {
// 总数是6 必须要执行任务的时候在去使用
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1;i <= 6; i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName());
countDownLatch.countDown();
},String.valueOf(i)).start();
}
countDownLatch.await();// 等待计数器归0 然后在向下执行
// -1
countDownLatch.countDown();
System.out.println("关门");
}
CyclicBarrier
介绍:允许一组线程全部等待彼此达到共同屏障点的同步辅助, 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。 CyclicBarrier支持一个可选的Runnable命令,每个屏障点运行一次,在派对中的最后一个线程到达之后,但在任何线程释放之前。 在任何一方继续进行之前,此屏障操作对更新共享状态很有用。
简单来说上面是一个减法计数器,那么这个就是个加分计数器
这个类有两个构造器,其中int 就表示着他需要到达的数,Runable就是他到达之后要触发启动的线程
具体方法作用:
代码示例:
public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
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();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
Semaphore
这个就不是像上面两个计数器,这是一个信号量,他指定一些许可证数量,线程在执行项目时,需要有许可证才能执行,没有必须要获取,当线程执行完项目,就会把许可证返回到信号量中,线程返回到池子中,供他人获取使用执行项目。不过请注意,当调用acquire()时,不会保持同步锁定,因为这将阻止某个项目返回到池中。 信号量封装了限制对池的访问所需的同步,与保持池本身一致性所需的任何同步分开。
信号量通常用于限制线程数,而不是访问某些(物理或逻辑)资源。
信号量被初始化为一个,并且被使用,使得它只有至多一个允许可用,可以用作互斥锁。
在这个类的构造器,有个布尔值,他用于指定公平还是非公平,也是就公平锁和非公平锁,
就如果我们使用ReentrantLock时 ,可以指定公平和非公平
这里就不对公平和非公平做过多的说明了
他的方法很多,大概就是获取与释放。
代码样例:
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 {
// release 释放
semaphore.release();
}
},String.valueOf(i)).start();
}
}
原理:
acquire: 获得,假设已经满了 ,等待被释放为止
release: 释放,会将当前的信号量释放,然后唤醒等待的线程
作用:多个共享资源互斥的使用!并发限流,控制最大的线程数