1.**
countdownlatch
**
多數用於任務拆分
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的時候,主線程纔會走 在最後等,
**
CyclicBarrier
**
總結 : 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
集齊東西執行最後任務
**
semaphore
**
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();
}
}
}