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();
}
}