1. 前言
随着计算机硬件的发展,多核处理器变得越来越常见。为了利用多核处理器的能力,我们需要编写能够并发执行的代码。然而,并发编程往往比较困难,因为不同线程之间的访问资源冲突可能导致不一致的结果。为了解决这个问题,Java提供了一些并发编程工具类,本文将介绍一些常用的并发编程工具类,并通过示例代码演示如何使用它们。
2. CountDownLatch
CountDownLatch
是一个同步工具类,它允许一个或多个线程等待其他线程完成操作后再继续执行。CountDownLatch
内部维护了一个计数器,初始化时指定计数器的值,并通过调用countDown()
方法来减少计数器的值。当计数器的值为0时,等待的线程将被唤醒。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int threadCount = 5;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
// 线程执行一些操作...
latch.countDown();
}).start();
}
latch.await();
System.out.println("所有线程执行完成");
}
}
上面的示例代码中,创建了5个线程,并通过CountDownLatch
来等待这5个线程执行完成。在每个线程执行完操作后,通过countDown()
方法减少计数器的值。主线程通过调用await()
方法来等待计数器的值变为0,从而实现等待所有线程执行完成。
3. CyclicBarrier
CyclicBarrier
也是一个同步工具类,它允许多个线程在一个临界点上互相等待。与CountDownLatch
不同的是,CyclicBarrier
可以被重置并可以循环使用。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
int threadCount = 5;
CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
System.out.println("所有线程都到达了临界点");
});
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
// 线程执行一些操作...
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
上面的示例代码中,创建了5个线程,并通过CyclicBarrier
来等待这5个线程到达临界点。主线程通过调用await()
方法来等待其它线程到达临界点,当所有线程都到达临界点时,将会执行CyclicBarrier
的构造函数中传入的Runnable
对象。
4. Semaphore
Semaphore
是一个计数信号量,它用来控制同时访问某个资源的线程数量。通常用于限制线程的数量或保护共享资源。
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) {
int threadCount = 5;
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
semaphore.acquire();
// 访问共享资源...
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
}
}
}
上面的示例代码中,创建了5个线程,并通过Semaphore
限制同时访问共享资源的线程数量为3。在每个线程访问共享资源之前,先通过acquire()
方法获取许可,如果没有许可将会阻塞线程。访问完成后,通过release()
方法释放许可。
5. BlockingQueue
BlockingQueue
是一个阻塞队列,它支持在队列为空时的线程等待,或者在队列满时的线程等待。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueDemo {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
new Thread(() -> {
while (true) {
try {
int value = queue.take();
// 处理从队列中取出的元素...
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
while (true) {
try {
queue.put(1);
// 向队列中添加元素...
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
上面的示例代码中,创建了一个长度为10的阻塞队列,并创建了两个线程,一个线程负责从队列中取出元素,另一个线程负责向队列中添加元素。当队列为空时,取出元素的线程将会阻塞等待;当队列满时,添加元素的线程将会阻塞等待。
6. Conclusion
本文介绍了Java中一些常用的并发编程工具类,并通过示例代码演示了它们的使用方法。这些工具类可以帮助我们更好地利用多核处理器,提高程序的执行效率。希望通过本文的介绍,读者对Java并发编程工具类有了更深入的了解。
本文来自极简博客,作者:指尖流年,转载请注明原文链接:Java中的并发编程工具类实战