背景
Java并发库提供了大量的线程同步类,用于实现线程同步。以下是一些常用的Java并发库中的线程同步类:
CountDownLatch:可以实现多个线程间的协作。
CyclicBarrier:它允许一组线程在到达某个公共屏障点之前阻塞,直到最后一个线程到达,然后所有线程再继续执行。
Semaphore:它控制一个资源(如数据库连接)的访问,保证在任意时刻只有一定数量的线程可以访问该资源。
Lock:它是一种互斥锁,它可以实现对共享资源的独占访问。
ReentrantLock:它是一种可重入的互斥锁,它支持多次获取锁,并且必须多次释放锁以释放锁的所有权。
实例CountDownLatch是Java中的一个同步工具类,它可以让一个或多个线程等待其他线程完成操作后再继续执行。它的主要作用是实现线程间的协调和同步。
CountDownLatch的原理是通过一个计数器来实现的。当我们创建一个CountDownLatch对象时,需要指定一个初始计数值。当一个线程完成了自己的任务后,可以调用CountDownLatch的countDown()方法来将计数值减1。而其他等待的线程可以调用CountDownLatch的await()方法来等待计数值变为0。
当计数值变为0时,所有等待的线程将被唤醒,可以继续执行后续的操作。
CountDownLatch常用于以下场景:
使用CountDownLatch可以有效地控制线程的执行顺序和协调线程之间的操作。它提供了一种简单且可靠的方式来实现线程间的同步和通信。
下面是一个使用CountDownLatch的多线程测试示例:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int numThreads = 5;
CountDownLatch latch = new CountDownLatch(numThreads);
for (int i = 0; i < numThreads; i++) {
Thread thread = new Thread(new WorkerThread(latch));
thread.start();
}
// 主线程等待所有子线程完成任务
latch.await();
System.out.println("All threads have completed their tasks.");
}
static class WorkerThread implements Runnable {
private final CountDownLatch latch;
public WorkerThread(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
System.out.println("Thread " + Thread.currentThread().getId() + " is running.");
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread " + Thread.currentThread().getId() + " has completed its task.");
// 操作完成后计数器减1
latch.countDown();
}
}
}
CyclicBarrier是Java并发包中的一个同步工具类,它可以让一组线程在达到某个共同的屏障点之前互相等待。CyclicBarrier的主要特点是可以重复使用,一旦所有线程都到达屏障点,屏障将被打破,所有线程将继续执行下一步操作。
CyclicBarrier的构造方法接收一个整数作为参数,表示参与线程的数量。当每个线程调用CyclicBarrier的await()方法时,它们将被阻塞,直到所有线程都到达屏障点。一旦所有线程都到达屏障点,屏障将被打破,所有线程将继续执行下一步操作。
CyclicBarrier还提供了一个可选的Runnable参数,它可以在所有线程到达屏障点之后执行一些额外的操作。这个Runnable对象只会在最后一个到达屏障点的线程中执行一次。
CyclicBarrier的一个常见应用场景是将一个大任务拆分成多个子任务,每个子任务由一个线程执行。当所有子任务都执行完成后,主线程可以继续执行下一步操作。下面是一个使用CyclicBarrier的多线程测试示例:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
int numThreads = 5;
CyclicBarrier barrier = new CyclicBarrier(numThreads, () -> {
System.out.println("All threads have reached the barrier.");
});
for (int i = 0; i < numThreads; i++) {
Thread thread = new Thread(new WorkerThread(barrier));
thread.start();
}
}
static class WorkerThread implements Runnable {
private final CyclicBarrier barrier;
public WorkerThread(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
System.out.println("Thread " + Thread.currentThread().getId() + " is running.");
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread " + Thread.currentThread().getId() + " has reached the barrier.");
try {
// 等待其他线程到达屏障点
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("Thread " + Thread.currentThread().getId() + " continues execution.");
}
}
}
总结
CountDownLatch和CyclicBarrier都是Java并发包中的工具类,用于协调多个线程的执行。
CountDownLatch用于等待多个线程完成某个任务,它的主要特点是一次性的,一旦计数器归零,就不能再次使用。CountDownLatch有两个核心方法:countDown()和await()。countDown()方法用于将计数器减1,await()方法用于等待计数器归零。
CyclicBarrier用于等待多个线程达到一个共同的屏障点,它的主要特点是可重复使用的。CyclicBarrier有两个核心方法:await()和reset()。await()方法用于等待所有线程到达屏障点,reset()方法用于重置屏障点。
下面是CountDownLatch和CyclicBarrier的一些对比:
用途:CountDownLatch用于等待多个线程完成某个任务,而CyclicBarrier用于等待多个线程达到一个共同的屏障点。使用次数:CountDownLatch是一次性的,一旦计数器归零,就不能再次使用。而CyclicBarrier是可重复使用的,可以多次使用。计数器的作用:CountDownLatch使用一个计数器来表示需要等待的线程数量,每个线程完成任务后会将计数器减1。CyclicBarrier使用一个计数器来表示需要等待的线程数量,每个线程到达屏障点后会调用await()方法等待其他线程。等待方式:CountDownLatch使用await()方法来等待计数器归零,而CyclicBarrier使用await()方法来等待所有线程到达屏障点。额外操作:CountDownLatch没有提供额外操作的机制。而CyclicBarrier可以在所有线程到达屏障点后执行指定的Runnable对象。
总的来说,CountDownLatch用于等待多个线程完成某个任务,而CyclicBarrier用于等待多个线程达到一个共同的屏障点,并可以执行额外的操作。
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777