CountDownLatch
CountDownLatch是Java并发包(java.util.concurrent)中的一种同步工具,它允许一个或多个线程等待其他线程完成任务后再执行。CountDownLatch通常用于在多线程环境下协调任务的执行顺序。
CountDownLatch的基本用法如下:
- 创建一个CountDownLatch实例:
import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(3); // 初始化CountDownLatch,需要3个线程调用countDown()方法 Thread thread1 = new Thread(new Task(latch, "Thread 1")); Thread thread2 = new Thread(new Task(latch, "Thread 2")); Thread thread3 = new Thread(new Task(latch, "Thread 3")); thread1.start(); thread2.start(); thread3.start(); } } class Task implements Runnable { private final CountDownLatch latch; private final String name; public Task(CountDownLatch latch, String name) { this.latch = latch; this.name = name; } @Override public void run() { try { System.out.println("Task " + name + " is running"); Thread.sleep(1000); // 模拟任务执行时间 System.out.println("Task " + name + " completed"); latch.countDown(); // 当计数器减至0时,所有等待的线程将被唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } }
在这个示例中,我们创建了一个名为CountDownLatchExample的类。main()方法中,我们创建了一个CountDownLatch实例,并为3个线程分别分配了任务。然后,我们启动这3个线程。每个线程在完成任务后调用CountDownLatch的countDown()方法,当计数器减至0时,主线程将被唤醒。
CyclicBarrier
CyclicBarrier是Java并发包(java.util.concurrent)中的一种同步工具,它允许一组线程在达到某个共享状态时一起阻塞。CyclicBarrier主要用于协调多个线程之间的顺序执行或同步。
CyclicBarrier的基本用法如下:
- 创建一个CyclicBarrier实例:
import java.util.concurrent.CyclicBarrier; public class CyclicBarrierExample { public static void main(String[] args) throws InterruptedException { CyclicBarrier barrier = new CyclicBarrier(3); // 初始化CyclicBarrier,需要3个线程调用await()方法 Thread thread1 = new Thread(new Task(barrier, "Thread 1")); Thread thread2 = new Thread(new Task(barrier, "Thread 2")); Thread thread3 = new Thread(new Task(barrier, "Thread 3")); thread1.start(); thread2.start(); thread3.start(); } } class Task implements Runnable { private final CyclicBarrier barrier; private final String name; public Task(CyclicBarrier barrier, String name) { this.barrier = barrier; this.name = name; } @Override public void run() { try { System.out.println("Task " + name + " is running"); Thread.sleep(1000); // 模拟任务执行时间 System.out.println("Task " + name + " completed"); barrier.await(); // 当所有线程都到达屏障时,主线程将被唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } }
在这个示例中,我们创建了一个名为CyclicBarrierExample的类。main()方法中,我们创建了一个CyclicBarrier实例,并为3个线程分别分配了任务。然后,我们启动这3个线程。每个线程在完成任务后调用CyclicBarrier的await()方法,当所有线程都到达屏障时,主线程将被唤醒。
Semaphore
Semaphore是Java并发包(java.util.concurrent)中的一种同步工具,它允许一组线程在达到某个共享状态时进行互斥访问。Semaphore有两个重要类型:
- Semaphore:Semaphore是一个计数信号量,用于控制同时访问的线程数量。创建一个Semaphore实例时,可以指定初始值和最大值。当一个线程尝试获取信号量时,如果计数小于最大值,则计数加1;否则,线程将等待直到计数减少到可用值。
- CountDownLatch:CountDownLatch也是一个计数信号量,但它允许一个或多个线程在到达某个共享状态后继续执行。创建一个CountDownLatch实例时,可以指定初始值。当一个或多个线程调用countDown()方法时,计数减1。当计数变为0时,所有等待的线程都将被唤醒。
下面是Semaphore的示例代码:
import java.util.concurrent.Semaphore; public class SemaphoreExample { public static void main(String[] args) throws InterruptedException { int initialValue = 5; // 初始化Semaphore,允许5个线程同时访问 int maxValue = 10; // 最大允许访问的线程数为10 Semaphore semaphore = new Semaphore(initialValue, maxValue); // 创建一个Semaphore实例,初始值为5,最大值为10 Thread thread1 = new Thread(new Task(semaphore)); Thread thread2 = new Thread(new Task(semaphore)); Thread thread3 = new Thread(new Task(semaphore)); Thread thread4 = new Thread(new Task(semaphore)); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } } class Task implements Runnable { private final Semaphore semaphore; public Task(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { try { semaphore.acquire(); // 尝试获取信号量,如果可用则计数加1,否则等待直到可用 System.out.println("Thread " + Thread.currentThread().getName() + " is running"); Thread.sleep(1000); // 模拟任务执行时间 semaphore.release(); // 释放信号量,计数减1 System.out.println("Thread " + Thread.currentThread().getName() + " completed"); } catch (InterruptedException e) { e.printStackTrace(); } } }
CoutDownLatch和CylicBarrier区别
CountDownLatch和CyclicBarrier都是Java并发包(java.util.concurrent)中用于协调多个线程之间同步的工具,但它们在实现上有所不同。
1.CountDownLatch
CountDownLatch是一个计数信号量,允许一个或多个线程在到达某个共享状态后继续执行。当一个或多个线程调用countDown()方法时,计数减1。当计数变为0时,所有等待的线程都将被唤醒。CountDownLatch通常与Semaphore一起使用,以控制同时访问的资源数量。
示例代码:
import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { int initialValue = 5; // 初始化CountDownLatch,允许5个线程同时执行countDown()方法 int maxValue = 10; // 最大允许执行的线程数为10 CountDownLatch countDownLatch = new CountDownLatch(initialValue); // 创建一个CountDownLatch实例,初始值为5 for (int i = 0; i < initialValue; i++) { new Thread(new Task(countDownLatch)).start(); // 创建多个线程,每个线程都调用countDown()方法 } countDownLatch.await(); // 所有线程执行完countDown()方法后,主线程才会继续执行 System.out.println("All threads completed"); } } class Task implements Runnable { private final CountDownLatch countDownLatch; public Task(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { try { countDownLatch.countDown(); // 每调用一次countDown()方法,计数减1 System.out.println("Thread " + Thread.currentThread().getName() + " is running"); Thread.sleep(1000); // 模拟任务执行时间 } catch (InterruptedException e) { e.printStackTrace(); } finally { countDownLatch.countDown(); // 在finally块中再次调用countDown()方法,确保所有线程都执行完countDown()方法后计数减1 } } }
CoutDownLatch是所有子线程都准备好后再同时开始,而CyclicBarrier是所有线程结束后再一起回到主线程。