好的例子胜过语言描述,注意观察测试结果,对于理解特别重要
CountDownLatch
- 例子
/**
* @CountDownLatch
* 阻塞某一个线程的对象,直到计数器为0
* ps:实际操作CountDownLatch可以阻塞任意数量的线程,这里先忽略
*
* @author it
*/
public class CountDownLatchDemo {
/**
* 计数器初始化次数为5
*/
CountDownLatch countDownLatch = new CountDownLatch(5);
public void start() throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 1; i <= 10; i++) {
final int awaitTime = i;
service.submit(() -> {
try {
TimeUnit.SECONDS.sleep(awaitTime);
System.out.println(LocalTime.now().getSecond() + "秒 : " + Thread.currentThread().getName());
// 计数器-1
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
});
}
// 计数器阻塞着,直到为0继续往后执行
countDownLatch.await();
System.out.println(LocalTime.now().getSecond() + "秒 : 计数器为0,阻塞终止 : " + Thread.currentThread().getName());
service.shutdown();
}
public static void main(String[] args) throws InterruptedException {
new CountDownLatchDemo().start();
}
}
- 测试结果
24秒 : pool-1-thread-1
25秒 : pool-1-thread-2
26秒 : pool-1-thread-3
27秒 : pool-1-thread-4
28秒 : pool-1-thread-5
28秒 : 计数器为0,阻塞终止 : main
29秒 : pool-1-thread-6
30秒 : pool-1-thread-7
31秒 : pool-1-thread-8
32秒 : pool-1-thread-9
33秒 : pool-1-thread-10
CyclicBarrier
基本例子
- 例子一
/**
* @CyclicBarrier
* 阻塞多个线程的对象,直到计数器为0,多个线程同时执行
*
* @author it
*/
public class CyclicBarrierDemo {
/**
* @parties
* 计数器初始化次数为5
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
public void start() throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 1; i <= 5; i++) {
final int awaitTime = i;
service.submit(() -> {
try {
TimeUnit.SECONDS.sleep(awaitTime);
// 计数器-1,计数器阻塞着,直到为0继续往后执行
cyclicBarrier.await();
System.out.println(LocalTime.now().getSecond() + "秒 : " + Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
});
}
System.out.println(LocalTime.now().getSecond() + "秒 : 主线程 : " + Thread.currentThread().getName());
service.shutdown();
}
public static void main(String[] args) throws InterruptedException {
new CyclicBarrierDemo().start();
}
}
- 测试结果
6秒 : 主线程 : main
11秒 : pool-1-thread-5
11秒 : pool-1-thread-4
11秒 : pool-1-thread-2
11秒 : pool-1-thread-3
11秒 : pool-1-thread-1
指定线程优先
- 例子二
/**
* @CyclicBarrier
* 阻塞多个线程的对象,直到计数器为0,多个阻塞线程同时执行
*
* @author it
*/
public class CyclicBarrierDemo2 {
/**
* @parties
* 计数器初始化次数为5
* @barrierAction
* 当计数器为0时,优先执行线程
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, ()->{
try {
System.out.println(LocalTime.now().getSecond() + "秒 : " + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
} catch(Exception e) {}
});
public void start() throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 1; i <= 5; i++) {
final int awaitTime = i;
service.submit(() -> {
try {
TimeUnit.SECONDS.sleep(awaitTime);
// 计数器-1,计数器阻塞着,直到为0继续往后执行
cyclicBarrier.await();
System.out.println(LocalTime.now().getSecond() + "秒 : " + Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
});
}
System.out.println(LocalTime.now().getSecond() + "秒 : 主线程 : " + Thread.currentThread().getName());
service.shutdown();
}
public static void main(String[] args) throws InterruptedException {
new CyclicBarrierDemo2().start();
}
}
- 测试结果
8秒有一个优先执行的线程
3秒 : 主线程 : main
8秒 : pool-1-thread-5
9秒 : pool-1-thread-5
9秒 : pool-1-thread-4
9秒 : pool-1-thread-1
9秒 : pool-1-thread-3
9秒 : pool-1-thread-2
指定线程优先
- 例子三
/**
* 循环使用CyclicBarrier
*
* @CyclicBarrier
* 阻塞多个线程的对象,直到计数器为0,多个线程同时执行
*
* @author it
*/
public class CyclicBarrierDemo3 {
/**
* @parties
* 计数器初始化次数为5
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
public void start() throws InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 1; i <= 15; i++) {
final int awaitTime = i;
service.submit(() -> {
try {
TimeUnit.SECONDS.sleep(awaitTime);
// 计数器-1,计数器阻塞着,直到为0继续往后执行
int await = cyclicBarrier.await();
if (await == 0) {
cyclicBarrier.reset();
}
System.out.println(LocalTime.now().getSecond() + "秒 : " + Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
});
}
System.out.println(LocalTime.now().getSecond() + "秒 : 主线程 : " + Thread.currentThread().getName());
service.shutdown();
}
public static void main(String[] args) throws InterruptedException {
new CyclicBarrierDemo3().start();
}
}
- 测试结果
53秒 : 主线程 : main
58秒 : pool-1-thread-5
58秒 : pool-1-thread-4
58秒 : pool-1-thread-3
58秒 : pool-1-thread-2
58秒 : pool-1-thread-1
3秒 : pool-1-thread-7
3秒 : pool-1-thread-9
3秒 : pool-1-thread-8
3秒 : pool-1-thread-6
3秒 : pool-1-thread-10
8秒 : pool-1-thread-15
8秒 : pool-1-thread-13
8秒 : pool-1-thread-12
8秒 : pool-1-thread-11
8秒 : pool-1-thread-14
Semaphore
- 例子
/**
* @Semaphore
* 资源控制的对象
*
* @author it
*/
public class SemaphoreDemo {
/**
* @permits - 在Semaphore管理下,只只允许同一个时间不超过两个线程(线程数量控制,即资源数据控制)
* @fair - 公平标志位,当为true时,等待越长的线程,优先级越高
*/
Semaphore semaphore = new Semaphore(2, true);
public void start() {
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
service.submit(() -> {
try {
// 拿一个资源
semaphore.acquire();
TimeUnit.SECONDS.sleep(1);
System.out.println(LocalTime.now().getSecond() + "秒 : " + Thread.currentThread().getName());
// 释放一个资源
semaphore.release();
} catch (Exception e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
public static void main(String[] args) {
new SemaphoreDemo().start();
}
}
- 测试结果
15秒 : pool-1-thread-2
15秒 : pool-1-thread-1
16秒 : pool-1-thread-3
16秒 : pool-1-thread-4
17秒 : pool-1-thread-6
17秒 : pool-1-thread-5
18秒 : pool-1-thread-8
18秒 : pool-1-thread-7
19秒 : pool-1-thread-9
19秒 : pool-1-thread-10