并发工具类
Java 提供了丰富的并发工具类来简化多线程编程,尤其是在 java.util.concurrent
包中。这些工具类能够有效解决线程间协作、同步等问题,帮助开发者编写更加安全、健壮的并发程序。
# 1. CountDownLatch
- 概念:
CountDownLatch
是一个同步辅助工具,允许一个或多个线程等待其他线程完成操作。通过一个计数器来实现,计数器初始值由线程数量决定。 - 使用场景:适用于需要等待多个线程完成某些操作之后,再继续执行的场景。例如,主线程等待多个子线程初始化完毕再开始工作。
- 示例代码:在这个例子中,主线程会等待所有子线程执行完毕后才会继续。
CountDownLatch latch = new CountDownLatch(3); Runnable worker = () -> { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " finished work."); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); } }; for (int i = 0; i < 3; i++) { new Thread(worker).start(); } try { latch.await(); System.out.println("All threads have finished work, proceeding..."); } catch (InterruptedException e) { e.printStackTrace(); }
# 2. CyclicBarrier
- 概念:
CyclicBarrier
是一个同步辅助工具,它允许一组线程相互等待,直到它们都到达某个公共屏障点。与CountDownLatch
不同的是,CyclicBarrier
可以被重复使用。 - 使用场景:适用于一组线程需要相互等待,直到所有线程都达到某个同步点的场景,例如并行计算中分阶段的结果合并。
- 示例代码:在这个例子中,所有线程到达屏障点后会执行指定的
CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("All parties have arrived, proceeding to the next step..."); }); Runnable worker = () -> { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " arrived at the barrier."); barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } }; for (int i = 0; i < 3; i++) { new Thread(worker).start(); }
Runnable
,然后继续执行后续任务。
# 3. Semaphore
- 概念:
Semaphore
是一种用于控制同时访问某特定资源的线程数量的工具,它通过许可证的方式来控制访问权限。 - 使用场景:适用于限制对资源的并发访问数量,例如控制对数据库连接的访问数目。
- 示例代码:在这个例子中,最多只能有两个线程同时获取许可证,其余线程将被阻塞。
Semaphore semaphore = new Semaphore(2); Runnable worker = () -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " acquired a permit."); Thread.sleep(2000); System.out.println(Thread.currentThread().getName() + " released a permit."); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }; for (int i = 0; i < 5; i++) { new Thread(worker).start(); }
# 4. ReentrantLock
- 概念:
ReentrantLock
是一个可重入的互斥锁,与synchronized
相比,它具有更高的灵活性和更多的控制选项。 - 使用场景:适用于需要显式锁定和解锁,并且需要尝试锁、超时锁等高级功能的场景。
- 示例代码:在这个例子中,线程尝试获取锁,若成功则执行相应操作,最后释放锁。
ReentrantLock lock = new ReentrantLock(); Runnable worker = () -> { try { if (lock.tryLock(1000, TimeUnit.MILLISECONDS)) { try { System.out.println(Thread.currentThread().getName() + " acquired the lock."); Thread.sleep(2000); } finally { lock.unlock(); System.out.println(Thread.currentThread().getName() + " released the lock."); } } else { System.out.println(Thread.currentThread().getName() + " could not acquire the lock."); } } catch (InterruptedException e) { e.printStackTrace(); } }; for (int i = 0; i < 3; i++) { new Thread(worker).start(); }
# 5. Exchanger
- 概念:
Exchanger
是一个用于在线程间交换数据的同步工具。它提供了一个同步点,两个线程可以在这个同步点交换数据。 - 使用场景:适用于需要在线程之间交换数据的场景,例如两个线程协作处理任务,一个生产数据,另一个使用数据。
- 示例代码:在这个例子中,生产者和消费者在线程间交换数据,只有在双方都准备好后才会交换。
Exchanger<String> exchanger = new Exchanger<>(); Runnable producer = () -> { try { String data = "Data from Producer"; System.out.println("Producer is exchanging: " + data); String response = exchanger.exchange(data); System.out.println("Producer received: " + response); } catch (InterruptedException e) { e.printStackTrace(); } }; Runnable consumer = () -> { try { String receivedData = exchanger.exchange("Data from Consumer"); System.out.println("Consumer received: " + receivedData); } catch (InterruptedException e) { e.printStackTrace(); } }; new Thread(producer).start(); new Thread(consumer).start();
# 6. Phaser
- 概念:
Phaser
是一种用于多阶段同步的工具,类似于CyclicBarrier
,但它支持更为复杂的阶段同步。它允许线程动态地加入或离开同步。 - 使用场景:适用于多阶段任务的同步控制,特别是在需要动态控制参与线程数的场景。
# 7. 总结
Java 中的并发工具类为多线程编程提供了强大的支持,从 CountDownLatch
到 CyclicBarrier
,再到 Semaphore
、ReentrantLock
、Exchanger
和 Phaser
,每个工具类都有其独特的应用场景。通过合理使用这些工具类,可以有效地简化线程之间的协作与同步,提升多线程程序的可维护性和健壮性。理解并发工具类的特性和适用场景,对于编写高效、可靠的并发程序至关重要。
上次更新: 2024/11/01, 13:45:14