在Java的多线程编程中,经常会遇到需要控制线程并发的情况。Semaphore、CountDownLatch、CyclicBarrier是Java中常用的三个并发工具类,本文将详细介绍它们的使用方法。
Semaphore是一种计数信号量,用于控制同时访问特定资源的线程数量。它通过协调各个线程,以保证合理的使用公共资源。
Semaphore有两种模式:公平模式和非公平模式。在公平模式下,线程获取许可的顺序与它们请求许可的顺序相同。在非公平模式下,线程获取许可的顺序是不确定的。
下面是一个Semaphore的示例:
import java.util.concurrent.Semaphore; public class SemaphoreExample { public static void main(String[] args) { Semaphore semaphore = new Semaphore(2); for (int i = 0; i < 5; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " acquire a permit."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); System.out.println(Thread.currentThread().getName() + " release a permit."); } } }); thread.start(); } } }
在上面的示例中,Semaphore的许可数量为2。一开始,有两个线程同时获取了许可,然后另外三个线程等待许可的释放。当有一个线程释放了许可之后,等待队列中的一个线程获取到了许可。
CountDownLatch是一种同步工具类,它可以让一个线程等待其他线程完成它们的工作之后再执行。
CountDownLatch通过一个计数器来实现。计数器的初始值为线程的数量。当一个线程完成了它的工作之后,计数器的值就会减1。当计数器的值为0时,表示所有线程都已经完成了工作,等待的线程可以继续执行。
下面是一个CountDownLatch的示例:
import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 0; i < 5; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + " has finished."); countDownLatch.countDown(); } }); thread.start(); } countDownLatch.await(); System.out.println("All threads have finished."); } }
在上面的示例中,有5个线程执行相同的任务。当一个线程完成它的工作之后,计数器的值就会减1。当所有线程都完成了工作,主线程才会继续执行。
CyclicBarrier是一种同步工具类,它可以让一组线程在到达一个屏障之前相互等待。当所有线程都到达屏障时,屏障才会打开,所有线程才能继续执行。
CyclicBarrier和CountDownLatch的区别在于:CountDownLatch是一次性的,计数器的值减到0之后就不能再次使用了;而CyclicBarrier可以循环使用,所有线程都到达屏障之后,计数器会重置,可以继续使用。
下面是一个CyclicBarrier的示例:
import java.util.concurrent.CyclicBarrier; class CyclicBarrierExample { public static void main(String[] args) { final int parties = 3; final CyclicBarrier cyclicBarrier = new CyclicBarrier(parties, new Runnable() { @Override public void run() { System.out.println("All parties have arrived at the barrier."); } }); for (int i = 0; i < parties; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " has arrived at the barrier."); cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }); thread.start(); } } }
在上面的示例中,有3个线程执行相同的任务。当一个线程到达屏障之后,就会调用await()方法等待其他线程到达屏障。当所有线程都到达屏障之后,屏障才会打开,所有线程才能继续执行。
本文为翻滚的胖子原创文章,转载无需和我联系,但请注明来自猿教程iskeys.com