CountDownLatch
相当于减法计数器
,任务执行完毕就调用countDown()方法,减到0时说明全部执行完毕,
否则会在 await() 阻塞
如果少调用了countDown(),即使任务全部执行完毕也会被一直阻塞。
public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(6);for (int i = 0; i < 6; i++) {new Thread(()->{System.out.println(Thread.currentThread().getName() + "Done");countDownLatch.countDown();}, String.valueOf(i)).start();}countDownLatch.await();System.out.println("全部执行完毕");}
CyclicBarrier
加法计数器
两种构造方法,
计数次数,到达次数后执行的 Runnable 任务
如果少调用了 await() 也会一直等。
public CyclicBarrier(int parties, Runnable barrierAction) {if (parties <= 0) throw new IllegalArgumentException();this.parties = parties;this.count = parties;this.barrierCommand = barrierAction;}public CyclicBarrier(int parties) {this(parties, null);}
public static void main(String[] args) throws InterruptedException {CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{System.out.println("全部执行完毕");});for (int i = 0; i < 7; i++) {// 加了 final 会把该变量复制到堆,这样线程才能访问到,否则执行完 for 循环局部变量就没了// jdk1.8后做了优化,如果不写 final 编译器会给你加上, 但是都不能修改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();}}).start();}}
Semaphore
信号量
同一时间只能有指定的线程数执行。
构造方法参数可以理解为限制的线程数
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
下面代码实现同一时间只能有3个线程执行,其他线程只能等待
semaphore.acquire(); 获得执行权,如果没有位置,就等待。
semaphore.release(); 释放,将当前信号量+1,唤醒等待线程。
作用:控制最大线程数
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "-抢占");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "-释放");
semaphore.release();
}
}).start();
}
}
