java线程同步CoutDownLatch、CylicBarrier、Semsphore

简介: java线程同步CoutDownLatch、CylicBarrier、Semsphore

CountDownLatch

CountDownLatch是Java并发包(java.util.concurrent)中的一种同步工具,它允许一个或多个线程等待其他线程完成任务后再执行。CountDownLatch通常用于在多线程环境下协调任务的执行顺序。

CountDownLatch的基本用法如下:

  1. 创建一个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的基本用法如下:

  1. 创建一个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有两个重要类型:

  1. Semaphore:Semaphore是一个计数信号量,用于控制同时访问的线程数量。创建一个Semaphore实例时,可以指定初始值和最大值。当一个线程尝试获取信号量时,如果计数小于最大值,则计数加1;否则,线程将等待直到计数减少到可用值。
  2. 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是所有线程结束后再一起回到主线程。

相关文章
|
1月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
86 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
3月前
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
Java多线程同步大揭秘:synchronized与Lock的终极对决!
80 5
|
1月前
|
存储 消息中间件 安全
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
【10月更文挑战第9天】本文介绍了如何利用JUC组件实现Java服务与硬件通过MQTT的同步通信(RRPC)。通过模拟MQTT通信流程,使用`LinkedBlockingQueue`作为消息队列,详细讲解了消息发送、接收及响应的同步处理机制,包括任务超时处理和内存泄漏的预防措施。文中还提供了具体的类设计和方法实现,帮助理解同步通信的内部工作原理。
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
|
21天前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
27天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
34 1
|
1月前
|
安全 Java 开发者
在多线程编程中,确保数据一致性与防止竞态条件至关重要。Java提供了多种线程同步机制
【10月更文挑战第3天】在多线程编程中,确保数据一致性与防止竞态条件至关重要。Java提供了多种线程同步机制,如`synchronized`关键字、`Lock`接口及其实现类(如`ReentrantLock`),还有原子变量(如`AtomicInteger`)。这些工具可以帮助开发者避免数据不一致、死锁和活锁等问题。通过合理选择和使用这些机制,可以有效管理并发,确保程序稳定运行。例如,`synchronized`可确保同一时间只有一个线程访问共享资源;`Lock`提供更灵活的锁定方式;原子变量则利用硬件指令实现无锁操作。
20 2
|
1月前
|
安全 调度 C#
STA模型、同步上下文和多线程、异步调度
【10月更文挑战第19天】本文介绍了 STA 模型、同步上下文和多线程、异步调度的概念及其优缺点。STA 模型适用于单线程环境,确保资源访问的顺序性;同步上下文和多线程提高了程序的并发性和响应性,但增加了复杂性;异步调度提升了程序的响应性和资源利用率,但也带来了编程复杂性和错误处理的挑战。选择合适的模型需根据具体应用场景和需求进行权衡。
|
1月前
多线程通信和同步的方式有哪些?
【10月更文挑战第6天】
100 0
|
3月前
|
Java 程序员
从0到1,手把手教你玩转Java多线程同步!
从0到1,手把手教你玩转Java多线程同步!
40 3
|
3月前
|
Java 测试技术
Java多线程同步实战:从synchronized到Lock的进化之路!
Java多线程同步实战:从synchronized到Lock的进化之路!
101 1
下一篇
无影云桌面