并发工具类
CountDownLatch
让主线程等待一组事件发生后继续执行
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
countDownLatch.countDown() //计数器减一
countDownLatch.await(); //线程等待,直到计数器为0
example
import java.util.concurrent.CountDownLatch;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(7);
IntStream.rangeClosed(1, 7).forEach(i -> {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + i);
countDownLatch.countDown();
}, String.valueOf(i)).start();
});
countDownLatch.await();
System.out.println("finish");
}
}
CyclicBarrier
CyclicBarrier的功能和CountDownLatch相反,是做加法。(集齐7颗龙珠才能召唤神龙)
一般采用的构造函数
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
即使当累计达到parties数目时,则执行runable。
example
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> System.out.println("召唤神龙"));
IntStream.rangeClosed(1, 14).forEach(i -> new Thread(() -> {
System.out.println(i);
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start());
}
}
1
4
2
6
3
5
7
召唤神龙
9
8
10
11
12
13
14
召唤神龙
Semaphore
1、用于多个共享资源的互斥使用
2、用于并发线程数的控制
Semaphore semaphore = new Semaphore(1);//相当于lock锁
semaphore就是有多个资源的lock,可以用餐桌理解,一个餐厅有固定数量的餐桌,来的人可以先获取到空的餐桌。当餐桌被分配光了以后,更多的人进来需要等待,直到前面的人离开。
example
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模拟三个座位
IntStream.range(0, 6).forEach(i -> {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + ":占到座位");
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
} finally {
System.out.println(Thread.currentThread().getName() + ":离开座位");
semaphore.release();
}
}, i + "线程").start();
});
}
}
0线程:占到座位
2线程:占到座位
1线程:占到座位
2线程:离开座位
0线程:离开座位
1线程:离开座位
4线程:占到座位
3线程:占到座位
5线程:占到座位
3线程:离开座位
5线程:离开座位
4线程:离开座位