我们在用Java进行并发多线程的代码开发时,JUC是我们经常使用的类。在这篇文章中,主要是介绍JUC包里提供的几个常用的辅助类,以及它是怎么使用来辅助我们进行多线程之间的通信开发的。
1、CountDownLatch类
可以设置进程的计数值,当指定数量的异步线程都调用了countDown后,主线程await才能被唤醒。
使用的实例代码如下所示。
public class CountDownLatchTest {
private static int count = 10;
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " is finished");
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println("All threads were finished");
}
}
在一些需要批量异步处理多个进程代码后进行阶段性分组操作处理的场景,就可以使用该CountDownLatch辅助类来实现。
2、CycliBarrier类
跟CountDownLatch类类似,CycliBarrier类也需要设置一个计数,当满足计数的数量的进程就绪调用await后就可以继续执行相应代码。
但是
如下代码所示,当所有线程都就绪(调用await)后,才会继续进行后面的代码以及cyclicBarrier中的线程。
public class CyclicBarrierTest {
private static int count = 10;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(count, () -> {
System.out.println("All threads are prepared");
});
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " is prepared");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is completed");
}).start();
}
}
}
跟CountDownLatch类不同的是,CountDownLatch类的计数固定无法进行变更,而CycliBarrier类则可以进行循环嵌套来迭代更新设置的屏障线程数。这种往往适合运用在一些异步线程数比较动态的情况下,来对多个异步线程进行结果汇聚的场景。
3、Semaphore类
控制占用资源的并发线程数,占用完资源释放后(调用release)才可让新的线程继续占用。
public class SemaphoreTest {
private static int count = 3;
public static void main(String[] args) {
//限制线程的并发数量
Semaphore semaphore = new Semaphore(count);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is running the limited part");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println(Thread.currentThread().getName() + "'s limited part was finihsed");
semaphore.release();
}
System.out.println(Thread.currentThread().getName() + " finished");
}).start();
}
}
}
入上所示,线程通过acquire来获取对应的线程锁,当占用的锁超过设置的值时,需要等待已占用资源的线程执行完并调用release方法释放资源,新的线程才能获取锁并继续执行。因此通过Semaphore类,可以比较简单地实现控制同时执行的线程数量,适用于一些需要限制多线程并发运行资源配置的场景。
以上就是介绍的三种常用的JUC辅助类,根据不同的使用场景,能够极大方便我们进行异步多线程的代码开发工作。