1.**
**
多数用于任务拆分
2.
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(20);
Service service = new Service(latch);
Runnable task = () -> service.exec();
for (int i = 0; i < 20; i++) {
Thread thread = new Thread(task);
thread.start();
}
System.out.println("主线程等待. ");
latch.await();
System.out.println("主线程完成等待. ");
}
}
public class Service {
private CountDownLatch latch;
public Service(CountDownLatch latch) {
this.latch = latch;
}
public void exec() {
try {
System.out.println(Thread.currentThread().getName() + " execute task. ");
sleep(2);
System.out.println(Thread.currentThread().getName() + " finished task. ");
} finally {
latch.countDown();
}
}
private void sleep(int seconds) {
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.输出
> Thread-0 execute task.
Thread-1 execute task.
Thread-2 execute task.
Thread-3 execute task.
Thread-4 execute task.
主线程等待.
Thread-0 finished task.
Thread-4 finished task.
Thread-3 finished task.
Thread-1 finished task.
Thread-2 finished task.
主线程完成等待.
4.适合任务拆分,比如 一个老板视察工作, 三个工人干活,三个工作都完成工作之后,老板再来视察
5.这样使用countdownlatch比较合适
6.提高了任务效率, 多个线程并发执行不同任务,主线程等待所有任务都执行完 才会执行
总结 : await()阻塞主线程, 做减法 , 计数器减为0的时候,主线程才会走 在最后等,
**
**
总结 : await()阻塞 做加法,加到一定程度, 那么主程序才会走 在线程中间等,有一个线程在等待执行最后的东西
public class Test {
ExecutorService fi = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws InterruptedException {
final CyclicBarrier barrier = new CyclicBarrier(50, new Runnable() {
@Override
public void run() {
System.out.println("集齐东西执行最后任务");
}
});
for(int i = 0 ; i< 50;i++){
final int r = i;
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(r+"开始集齐东西"+Thread.currentThread().getName());
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}).start();
}
System.out.println("开始集齐东西"+Thread.currentThread().getName());
}
}
输出
0开始集齐东西Thread-0
1开始集齐东西Thread-1
2开始集齐东西Thread-2
3开始集齐东西Thread-3
4开始集齐东西Thread-4
5开始集齐东西Thread-5
6开始集齐东西Thread-6
7开始集齐东西Thread-7
8开始集齐东西Thread-8
9开始集齐东西Thread-9
10开始集齐东西Thread-10
11开始集齐东西Thread-11
12开始集齐东西Thread-12
13开始集齐东西Thread-13
14开始集齐东西Thread-14
15开始集齐东西Thread-15
16开始集齐东西Thread-16
17开始集齐东西Thread-17
18开始集齐东西Thread-18
19开始集齐东西Thread-19
20开始集齐东西Thread-20
21开始集齐东西Thread-21
22开始集齐东西Thread-22
23开始集齐东西Thread-23
24开始集齐东西Thread-24
25开始集齐东西Thread-25
26开始集齐东西Thread-26
27开始集齐东西Thread-27
28开始集齐东西Thread-28
29开始集齐东西Thread-29
30开始集齐东西Thread-30
31开始集齐东西Thread-31
32开始集齐东西Thread-32
33开始集齐东西Thread-33
34开始集齐东西Thread-34
35开始集齐东西Thread-35
36开始集齐东西Thread-36
37开始集齐东西Thread-37
38开始集齐东西Thread-38
39开始集齐东西Thread-39
49开始集齐东西Thread-49
40开始集齐东西Thread-40
48开始集齐东西Thread-48
47开始集齐东西Thread-47
46开始集齐东西Thread-46
45开始集齐东西Thread-45
44开始集齐东西Thread-44
43开始集齐东西Thread-43
42开始集齐东西Thread-42
41开始集齐东西Thread-41
集齐东西执行最后任务
**
**
lock和 synchronized 默认是非公平锁, 非公平锁效率高 (可以加塞)
Semaphore semaphore = new Semaphore(3,false);
总结 : 信号量, 多个线程抢多个资源 可以代替 lock , synchronized
1.多个共享资源互斥使用
2.并发线程数控制
举个例子 Semaphore semaphore = new Semaphore(3,false); 可以当停车场的车位 只有三个,
线程有6个 ,可以当做是车
semaphore.acquire(); 代表一部车占位了,
semaphore.release(); 释放停车位 最好放在finally里面
值是可以伸缩的
public class Test{
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(30,true);
for(int i = 0 ; i < 180 ; i++){
new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("占用停车位 "+ Thread.currentThread().getName());
Thread.sleep(3000);
System.out.println("睡三秒离开车位 "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
}
}).start();
}
}
}