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是所有线程结束后再一起回到主线程。

相关文章
|
2月前
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
Java多线程同步大揭秘:synchronized与Lock的终极对决!
58 5
|
2月前
|
安全 Java 开发者
Java多线程同步:synchronized与Lock的“爱恨情仇”!
Java多线程同步:synchronized与Lock的“爱恨情仇”!
81 5
|
2月前
|
Java 程序员
从0到1,手把手教你玩转Java多线程同步!
从0到1,手把手教你玩转Java多线程同步!
22 3
|
2月前
|
Java 测试技术
Java多线程同步实战:从synchronized到Lock的进化之路!
Java多线程同步实战:从synchronized到Lock的进化之路!
86 1
|
2月前
|
存储 算法 Java
Java 中的同步集合和并发集合
【8月更文挑战第22天】
25 5
|
2月前
|
存储 Java 开发者
HashMap线程安全问题大揭秘:ConcurrentHashMap、自定义同步,一文让你彻底解锁!
【8月更文挑战第24天】HashMap是Java集合框架中不可或缺的一部分,以其高效的键值对存储和快速访问能力广受开发者欢迎。本文深入探讨了HashMap在JDK 1.8后的底层结构——数组+链表+红黑树混合模式,这种设计既利用了数组的快速定位优势,又通过链表和红黑树有效解决了哈希冲突问题。数组作为基石,每个元素包含一个Node节点,通过next指针形成链表;当链表长度过长时,采用红黑树进行优化,显著提升性能。此外,还介绍了HashMap的扩容机制,确保即使在数据量增大时也能保持高效运作。通过示例代码展示如何使用HashMap进行基本操作,帮助理解其实现原理及应用场景。
34 1
|
2月前
|
安全 Java
Java 中同步 ArrayList 的详细指南
【8月更文挑战第23天】
44 1
|
2月前
|
传感器 C# 监控
硬件交互新体验:WPF与传感器的完美结合——从初始化串行端口到读取温度数据,一步步教你打造实时监控的智能应用
【8月更文挑战第31天】本文通过详细教程,指导Windows Presentation Foundation (WPF) 开发者如何读取并处理温度传感器数据,增强应用程序的功能性和用户体验。首先,通过`.NET Framework`的`Serial Port`类实现与传感器的串行通信;接着,创建WPF界面显示实时数据;最后,提供示例代码说明如何初始化串行端口及读取数据。无论哪种传感器,只要支持串行通信,均可采用类似方法集成到WPF应用中。适合希望掌握硬件交互技术的WPF开发者参考。
40 0
|
2月前
|
开发者 C# 存储
WPF开发者必读:资源字典应用秘籍,轻松实现样式与模板共享,让你的WPF应用更上一层楼!
【8月更文挑战第31天】在WPF开发中,资源字典是一种强大的工具,用于共享样式、模板、图像等资源,提高了应用的可维护性和可扩展性。本文介绍了资源字典的基础知识、创建方法及最佳实践,并通过示例展示了如何在项目中有效利用资源字典,实现资源的重用和动态绑定。
43 0
|
2月前
|
开发者 Java Spring
【绝技揭秘】掌握Vaadin数据绑定:一键同步Java对象,告别手动数据烦恼,轻松玩转Web应用开发!
【8月更文挑战第31天】Vaadin不仅是一个功能丰富的Java Web应用框架,还提供了强大的数据绑定机制,使开发者能轻松连接UI组件与后端Java对象,简化Web应用开发流程。本文通过创建一个简单的用户信息表单示例,详细介绍了如何使用Vaadin的`Binder`类实现数据绑定,包括字段与模型属性的双向绑定及数据验证。通过这个示例,开发者可以更专注于业务逻辑而非繁琐的数据同步工作,提高开发效率和应用可维护性。
51 0
下一篇
无影云桌面