目录
一. 闭锁(CountDownLatch)
- 设计原理:一个线程或者一组线程等待其他线程完成之后,再继续运行。不可重用。计数值减一。
- 应用场景:
(1) 一个资源需要初始化才能使用,然后需要这个资源的操作都需要等待该资源初始化。
(2)某个服务在其依赖的服务启动之后再进行启动。
(3)等待所有的参与者准备就绪再进行执行。
3. demo:
package com.test.countdownlatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public class CountDownLatchDemo {
public static void main(String[] args) {
long executeTime = task(10, new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "准备就绪");
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(5));
System.out.println(Thread.currentThread().getName() + "完成比赛");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("比赛用时:"+ executeTime + "ms");
}
public static long task(int threadNum, Runnable runnable) {
CountDownLatch latch1 = new CountDownLatch(1);
CountDownLatch latch2 = new CountDownLatch(10);
for (int i = 0; i < threadNum; i++) {
new Thread(() -> {
try {
latch1.await();
try {
runnable.run();
} finally {
latch2.countDown();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
long startTime = System.currentTimeMillis();
latch1.countDown();
try {
latch2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("比赛结束");
return endTime - startTime;
}
}
二. 栅栏( CyclicBarrier )
1. 设计原理:一组线程之间相互等待,直至共同达到某个状态,再继续操作。 可重用。计数值加一。
2. demo:
package com.test.cyclicbarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public class CyclicBarrierDemo2 {
public static void main(String[] args) {
int threadNum = 10;
CyclicBarrier barrier = new CyclicBarrier(threadNum, () -> System.out.println("任务完成"));
for (int i = 0; i < threadNum; i++) {
new Thread(new Barrier(i, barrier)).start();
}
}
}
class Barrier implements Runnable {
private int num;
private CyclicBarrier cyclicBarrier;
public Barrier(int num, CyclicBarrier cyclicBarrier) {
this.num = num;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(num);
System.out.println(Thread.currentThread().getName() + "子程序完成");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
三. 信号量(Semaphore)
用来控制并发数量
应用场景:资源池,对容器施加边界。
package com.test.semaphore;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Semaphore;
public class BoundedHashSet<T> {
private final Semaphore semaphore;
private final Set<T> set;
public BoundedHashSet(int bound) {
this.semaphore = new Semaphore(bound);
this.set = Collections.synchronizedSet(new HashSet<>());
}
public boolean add(T t) {
boolean wasAdded = false;
try {
semaphore.acquire();
wasAdded = set.add(t);
return wasAdded;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (!wasAdded)
semaphore.release();
}
return false;
}
public boolean remove(Object obj) {
boolean removed = set.remove(obj);
if (removed)
semaphore.release();
return removed;
}
}
package com.test.semaphore;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo extends Semaphore {
public SemaphoreDemo(int permits, boolean fair) {
super(permits, fair);
}
public static void main(String[] args) {
Semaphore semaphore = new SemaphoreDemo(3, true);
for (int i = 0; i < 20; i++) {
new Thread(() -> {
try {
semaphore.acquire();
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "任务完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
}
}
}
四. Exchanger
package com.test.exchanger;
import java.util.concurrent.Exchanger;
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
String str1 = "hello";
String str2 = "world";
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "===>str1初始值:" + str1);
try {
Object obj1 = exchanger.exchange(str1);
System.out.println(Thread.currentThread().getName() + "===>str1交换值:" + obj1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "===>str2初始值:" + str2);
try {
Object obj2 = exchanger.exchange(str2);
System.out.println(Thread.currentThread().getName() + "===>str2交换值:" + obj2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}