JavaSE(27)——并发工具类
程序员文章站
2024-01-13 19:38:58
...
并发工具类
java为开发者提供了三个同步工具类,说白了就是为了能够更好控制线程之间的通讯问题。
- CountDownLatch (闭锁)
- CyclicBarrier (栅栏)
- Semaphore (信号量)
1. CountDownLatch
CountDownLatch是一个同步的辅助类,允许一个或多个线程一直等待,直到其他线程完成他们的操作。
常用的API有两个:await()
和countDown()
- count初始化CountDownLatch,然后需要等待的线程调用await方法。await方法会一直受阻塞直到count = 0。而其他线程完成自己的操作后,调用
countDown
使计数器count减1。当count减到0时,所有在等待的线程均会被释放 - 原理就是通过count变量来控制等待,如果count值为0(其他线程的任务都完成了),那就可以继续执行。
举例:
public static void main(String[] args) throws InterruptedException {
final int threadNum = 2;
CountDownLatch latch = new CountDownLatch(threadNum);
new Thread(() -> {
System.out.println("线程1开始运行");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1继续运行");
}).start();
new Thread(() -> {
System.out.println("线程2开始运行");
try {
Thread.sleep(2000);
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程2继续运行");
}).start();
new Thread(() -> {
System.out.println("线程3开始运行");
try {
Thread.sleep(5000);
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程3继续运行");
}).start();
}
public static void out(int threadNum){
System.out.println("threadNum==="+threadNum);
}
2. CyclicBarrier
CyclicBarrier允许一组线程互动等待,等待到达某个公共屏障点。叫做cyclic是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。
也就是说,当CyclicBarrier的parties全部await()
之后,才可以继续往下运行。
举例:
public static void main(String[] args) throws InterruptedException {
final int threadNum = 5;
CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum);
for (int i = 0; i < threadNum; i++) {
final int thread = i;
new Thread(() -> {
try {
Thread.sleep(thread*1000);
System.out.println("线程"+thread+"已准备就绪");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("线程"+thread+"开始运行");
}).start();
}
}
3. Semaphore
Semaphore实际上就是可以控制同时访问同一的线程的个数,它维护了一组**“许可”**
- 当调用
acquire()
方法时,会消费一个许可证。如果没有许可证了,会阻塞起来-
acquire(int permits)
:一次消费permits个许可证
-
- 当调用
tryAcquire()
方法时,会尝试获取一个许可证,如果没有许可证,不会阻塞,只返回false。-
tryAcquire(int permits)
:一次获取permits个许可证 -
tryAcquire(long timeout, TimeUnit unit)
:允许等待timeout时间后再返回false -
tryAcquire(int permits, long timeout, TimeUnit unit)
:前两种方法的结合
-
- 当调用
release()
方法时,会添加一个许可证。 - 这些许可证的数量就是一个count变量
举例:
public static void main(String[] args) throws InterruptedException {
final int threadNum = 5;
final int once = 2;
Semaphore semaphore = new Semaphore(threadNum*once);
for (int i = 0; i < 20; i++) {
final int thread = i;
new Thread(() -> {
try {
System.out.println("线程"+thread+"正在等待许可");
semaphore.acquire(once);
System.out.println("线程"+thread+"开始运行");
Thread.sleep(1000);
semaphore.release(once);
System.out.println("线程"+thread+"执行完毕");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
4. 总结
Java为我们提供了三个同步工具类:
-
CountDownLatch(闭锁)
-
- 某个线程等待其他线程执行完毕后,它才执行(其他线程等待某个线程执行完毕后,它才执行)
-
CyclicBarrier(栅栏)
-
- 一组线程互相等待至某个状态,这组线程再同时执行。
-
Semaphore(信号量)
-
- 控制一组线程同时执行。
上一篇: 算法竞赛中c++一些需要注意的错误
推荐阅读