在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
