Java一分钟之-并发编程:线程间通信(Phaser, CyclicBarrier, Semaphore)

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
大数据开发治理平台 DataWorks,不限时长
简介: 【5月更文挑战第19天】Java并发编程中,Phaser、CyclicBarrier和Semaphore是三种强大的同步工具。Phaser用于阶段性任务协调,支持动态注册;CyclicBarrier允许线程同步执行,适合循环任务;Semaphore控制资源访问线程数,常用于限流和资源池管理。了解其使用场景、常见问题及避免策略,结合代码示例,能有效提升并发程序效率。注意异常处理和资源管理,以防止并发问题。

在Java并发编程中,线程间的协作与通信是实现复杂并发逻辑的关键。Phaser, CyclicBarrier, 和 Semaphore 是Java并发包提供的强大工具,它们分别适用于不同的同步需求。本文将深入浅出地介绍这三个组件的使用场景、常见问题及避免策略,并附上代码示例。
image.png

1. Phaser - 阶段性任务协调器

介绍

Phaser 是一个灵活的同步屏障,支持动态注册和取消注册参与者,适用于有多个阶段的任务执行流程。

常见问题与避免策略

  • 问题:过度依赖动态注册,导致阶段结束条件难以预测。
  • 避免:明确每个阶段的预期参与者数量,适时使用arriveAndDeregister方法。

示例

import java.util.concurrent.Phaser;

public class PhaserDemo {
   
   
    public static void main(String[] args) {
   
   
        Phaser phaser = new Phaser(1); // 初始参与者为1(主线程)

        for (int i = 0; i < 3; i++) {
   
   
            new Thread(() -> {
   
   
                System.out.println(Thread.currentThread().getName() + " arrived.");
                phaser.arriveAndAwaitAdvance(); // 到达并等待所有到达
                System.out.println(Thread.currentThread().getName() + " continuing.");
            }, "Thread-" + (i+1)).start();
        }

        phaser.arriveAndDeregister(); // 主线程到达并注销
    }
}

2. CyclicBarrier - 循环屏障

介绍

CyclicBarrier 允许一组线程相互等待,直到达到某个屏障点后一起继续执行。它支持重置和重复使用,适用于循环执行的任务。

常见问题与避免策略

  • 问题:忘记处理BrokenBarrierException,导致程序意外终止。
  • 避免:在run()方法中捕获并适当处理此异常。

示例

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
   
   
    public static void main(String[] args) {
   
   
        int parties = 3;
        CyclicBarrier barrier = new CyclicBarrier(parties, () -> System.out.println("All threads reached the barrier."));

        for (int i = 0; i < parties; i++) {
   
   
            new Thread(() -> {
   
   
                try {
   
   
                    System.out.println(Thread.currentThread().getName() + " is waiting on barrier.");
                    barrier.await(); // 等待所有线程到达
                    System.out.println(Thread.currentThread().getName() + " continued.");
                } catch (InterruptedException | BrokenBarrierException e) {
   
   
                    e.printStackTrace();
                }
            }, "Thread-" + (i+1)).start();
        }
    }
}

3. Semaphore - 信号量

介绍

Semaphore 是一种计数信号量,用于控制同时访问特定资源的线程数量,常用于限流和资源池管理。

常见问题与避免策略

  • 问题:未正确释放信号量,导致资源泄露。
  • 避免:确保acquirerelease成对出现,即使在异常情况下也要释放。

示例

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
   
   
    public static void main(String[] args) {
   
   
        Semaphore semaphore = new Semaphore(2); // 允许两个线程同时访问

        for (int i = 0; i < 5; i++) {
   
   
            new Thread(() -> {
   
   
                try {
   
   
                    semaphore.acquire(); // 获取许可
                    System.out.println(Thread.currentThread().getName() + " entered the critical section.");
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + " leaving the critical section.");
                } catch (InterruptedException e) {
   
   
                    Thread.currentThread().interrupt();
                } finally {
   
   
                    semaphore.release(); // 释放许可
                }
            }, "Thread-" + (i+1)).start();
        }
    }
}

总结而言,Phaser, CyclicBarrier, 和 Semaphore 分别提供了不同维度的线程间通信和同步机制。理解它们的特性和正确使用,是实现高效并发程序的关键。在实际应用中,应根据具体场景选择合适的工具,并注意异常处理和资源管理,以避免常见的并发陷阱。

目录
相关文章
|
19小时前
|
存储 JSON 算法
Python中的并发编程(4)多线程发送网络请求
Python中的并发编程(4)多线程发送网络请求
|
19小时前
|
Java Python
Python中的并发编程(3)线程池、锁
Python中的并发编程(3)线程池、锁
|
19小时前
|
并行计算 Python
Python中的并发编程(2)线程的实现
Python中的并发编程(2)线程的实现
Python中的并发编程(2)线程的实现
|
1天前
|
Java
Java 中 CountDownLatch 和 CyclicBarrier 有什么不同?
Java 中 CountDownLatch 和 CyclicBarrier 有什么不同?v
7 0
|
2天前
|
Java API
详细探究Java多线程的线程状态变化
Java多线程的线程状态主要有六种:新建(NEW)、可运行(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)和终止(TERMINATED)。线程创建后处于NEW状态,调用start()后进入RUNNABLE状态,表示准备好运行。当线程获得CPU资源,开始执行run()方法时,它处于运行状态。线程可以因等待锁或调用sleep()等方法进入BLOCKED或等待状态。线程完成任务或发生异常后,会进入TERMINATED状态。
|
2天前
|
存储 安全 Java
Java多线程中线程安全问题
Java多线程中的线程安全问题主要涉及多线程环境下对共享资源的访问可能导致的数据损坏或不一致。线程安全的核心在于确保在多线程调度顺序不确定的情况下,代码的执行结果始终正确。常见原因包括线程调度随机性、共享数据修改以及原子性问题。解决线程安全问题通常需要采用同步机制,如使用synchronized关键字或Lock接口,以确保同一时间只有一个线程能够访问特定资源,从而保持数据的一致性和正确性。
|
2天前
|
监控 安全 Java
Java多线程的使用
Java多线程允许程序同时执行多个任务,提高了系统的整体性能和响应速度。通过创建Thread类或其子类的实例,或使用Runnable接口,Java开发者可以定义并发执行的代码段。多线程在处理复杂任务、资源共享、网络通信等方面具有显著优势,但也需要注意线程安全、同步和死锁等问题。Java提供了丰富的API和工具来处理这些并发问题,使多线程编程更加高效和可靠。
|
2天前
|
API
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
6 1
|
9天前
|
缓存 Java 测试技术
Java性能优化(八)-多线程调优-线程池大小设置
Java性能优化(八)-多线程调优-线程池大小设置
11 0
|
11天前
|
安全 Java 容器
多线程(进阶四:线程安全的集合类)
多线程(进阶四:线程安全的集合类)
15 0