在Java并发编程中,java.util.concurrent
包(通常简称为JUC)提供了许多辅助类,这些类可以帮助开发者更容易地管理多线程程序中的并发问题。以下是JUC中一些常用的辅助类及其用途:
1. ExecutorService
- 用途:
ExecutorService
是一个接口,它定义了执行线程任务的标准方法。它提供了一种灵活的方式来管理线程池,可以用来执行单个任务或批量任务。 - 示例:
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个固定大小的线程池 executor.execute(() -> System.out.println("Hello from a thread!")); // 执行一个Runnable任务 executor.shutdown(); // 关闭线程池
2. Future
- 用途:
Future
是一个接口,它表示一个异步计算的结果。Future
对象可以用来获取计算的结果或检查计算的状态。 - 示例:
ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Integer> future = executor.submit(() -> 42); // 提交一个Callable任务 Integer result = future.get(); // 获取计算结果
3. CountDownLatch
- 用途:
CountDownLatch
是一个同步辅助类,它允许一个或多个线程等待其他线程完成某些操作。它通过一个计数器来控制线程的等待,当计数器减至零时,所有等待的线程会被释放。 - 示例:
CountDownLatch latch = new CountDownLatch(3); new Thread(() -> { System.out.println("Doing some work..."); latch.countDown(); // 减少计数器 }).start(); // 等待所有任务完成 latch.await(); System.out.println("All tasks completed.");
4. CyclicBarrier
- 用途:
CyclicBarrier
是一个同步辅助类,它允许一组线程相互等待,直到到达某个公共屏障点。与CountDownLatch
不同,CyclicBarrier
可以在每次所有参与线程到达屏障点后重置,以便再次使用。 - 示例:
CyclicBarrier barrier = new CyclicBarrier(3); for (int i = 0; i < 3; i++) { new Thread(() -> { System.out.println("Thread is waiting at the barrier."); try { barrier.await(); // 等待其他线程到达屏障点 } catch (Exception e) { e.printStackTrace(); } System.out.println("Thread has passed the barrier."); }).start(); }
5. Semaphore
- 用途:
Semaphore
是一个同步辅助类,它管理一个许可集。线程可以获取许可,从而获得访问共享资源的权限。Semaphore
可用于控制对有限资源的访问数量。 - 示例:
Semaphore semaphore = new Semaphore(2); // 最多允许两个线程访问 new Thread(() -> { try { semaphore.acquire(); // 获取许可 System.out.println("Accessing shared resource..."); Thread.sleep(1000); semaphore.release(); // 释放许可 } catch (Exception e) { e.printStackTrace(); } }).start();
6. Exchanger
- 用途:
Exchanger
是一个同步辅助类,它允许两个线程交换数据。当两个线程到达Exchanger
时,它们会被阻塞,直到对方也到达,此时它们可以交换数据。 - 示例:
Exchanger<String> exchanger = new Exchanger<>(); new Thread(() -> { try { String data = "Data from thread A"; System.out.println("Thread A is waiting to exchange data."); String received = exchanger.exchange(data); // 等待交换数据 System.out.println("Thread A received: " + received); } catch (Exception e) { e.printStackTrace(); } }).start(); new Thread(() -> { try { String data = "Data from thread B"; System.out.println("Thread B is waiting to exchange data."); String received = exchanger.exchange(data); // 等待交换数据 System.out.println("Thread B received: " + received); } catch (Exception e) { e.printStackTrace(); } }).start();
7. Phaser
- 用途:
Phaser
类似于CyclicBarrier
,但它提供了一些额外的功能,例如动态注册和注销参与者的能力,以及更细粒度的控制。 - 示例:
Phaser phaser = new Phaser(2); // 初始参与者数 new Thread(() -> { System.out.println("Thread 1 started."); phaser.arriveAndAwaitAdvance(); // 等待其他参与者 System.out.println("Thread 1 has passed the phase."); }).start(); new Thread(() -> { System.out.println("Thread 2 started."); phaser.arriveAndAwaitAdvance(); // 等待其他参与者 System.out.println("Thread 2 has passed the phase."); }).start();
8. CompletionService
- 用途:
CompletionService
是一个接口,它提供了一个统一的接口来处理异步任务的完成事件。它结合了ExecutorService
和Future
的功能,可以用来管理异步任务的完成状态。 - 示例:
ExecutorService executor = Executors.newFixedThreadPool(2); CompletionService<Integer> completionService = new ExecutorCompletionService<>(executor); completionService.submit(() -> 42); // 提交一个Callable任务 completionService.submit(() -> 100); // 提交另一个Callable任务 for (int i = 0; i < 2; i++) { Future<Integer> future = completionService.take(); // 获取已完成的任务 System.out.println("Result: " + future.get()); }
9. DelayedQueue
- 用途:
DelayedQueue
是一个队列,它保存了具有延迟属性的对象。只有当对象的延迟过期后,它们才能从队列中被提取或检索。 - 示例:
DelayQueue<DelayedElement> queue = new DelayQueue<>(); queue.put(new DelayedElement(5000L)); // 添加一个延迟5秒的元素 DelayedElement element = queue.take(); // 等待延迟过期后获取元素 System.out.println("Element was taken after " + element.getDelay(TimeUnit.MILLISECONDS) + " ms.");
10. Atomic*
类
- 用途:
AtomicInteger
、AtomicLong
等原子类提供了基本类型的原子更新操作,可以用于实现高效的并发操作。 - 示例:
AtomicInteger counter = new AtomicInteger(0); new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.incrementAndGet(); // 原子地递增计数器 } }).start(); // 等待所有线程完成 // ... System.out.println("Final count: " + counter.get());
这些辅助类提供了丰富的功能,可以帮助开发者更轻松地管理线程之间的同步和协作,从而构建出高效、可靠的并发程序。在实际开发中,根据具体的需求选择合适的工具类非常重要。