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

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,5000CU*H 3个月
简介: 【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 分别提供了不同维度的线程间通信和同步机制。理解它们的特性和正确使用,是实现高效并发程序的关键。在实际应用中,应根据具体场景选择合适的工具,并注意异常处理和资源管理,以避免常见的并发陷阱。

目录
相关文章
|
7月前
|
Java 编译器 开发者
深入理解Java内存模型(JMM)及其对并发编程的影响
【9月更文挑战第37天】在Java的世界里,内存模型是隐藏在代码背后的守护者,它默默地协调着多线程环境下的数据一致性和可见性问题。本文将揭开Java内存模型的神秘面纱,带领读者探索其对并发编程实践的深远影响。通过深入浅出的方式,我们将了解内存模型的基本概念、工作原理以及如何在实际开发中正确应用这些知识,确保程序的正确性和高效性。
|
1月前
|
Java
【源码】【Java并发】【AQS】从ReentrantLock、Semaphore、CutDownLunch、CyclicBarrier看AQS源码
前言 主播觉得,AQS的原理,就是通过这2个队列的协助,实现核心功能,同步队列(CLH队列)和条件队列(Condition队列)。 同步队列(CLH队列) 作用:管理需要获...
79 18
【源码】【Java并发】【AQS】从ReentrantLock、Semaphore、CutDownLunch、CyclicBarrier看AQS源码
|
5月前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
82 0
|
8月前
|
Java
JAVA并发编程系列(7)Semaphore信号量剖析
腾讯T2面试,要求在3分钟内用不超过20行代码模拟地铁安检进站过程。题目设定10个安检口,100人排队,每人安检需5秒。实际中,这种题目主要考察并发编程能力,特别是多个线程如何共享有限资源。今天我们使用信号量(Semaphore)实现,限制同时进站的人数,并通过信号量控制排队和进站流程。并详细剖析信号量核心原理和源码。
|
9月前
|
Java 程序员 调度
【JAVA 并发秘籍】进程、线程、协程:揭秘并发编程的终极武器!
【8月更文挑战第25天】本文以问答形式深入探讨了并发编程中的核心概念——进程、线程与协程,并详细介绍了它们在Java中的应用。文章不仅解释了每个概念的基本原理及其差异,还提供了实用的示例代码,帮助读者理解如何在Java环境中实现这些并发机制。无论你是希望提高编程技能的专业开发者,还是准备技术面试的求职者,都能从本文获得有价值的见解。
129 1
|
6月前
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
645 6
|
6月前
|
设计模式 安全 Java
Java 多线程并发编程
Java多线程并发编程是指在Java程序中使用多个线程同时执行,以提高程序的运行效率和响应速度。通过合理管理和调度线程,可以充分利用多核处理器资源,实现高效的任务处理。本内容将介绍Java多线程的基础概念、实现方式及常见问题解决方法。
275 1
|
6月前
|
存储 缓存 安全
Java内存模型(JMM):深入理解并发编程的基石####
【10月更文挑战第29天】 本文作为一篇技术性文章,旨在深入探讨Java内存模型(JMM)的核心概念、工作原理及其在并发编程中的应用。我们将从JMM的基本定义出发,逐步剖析其如何通过happens-before原则、volatile关键字、synchronized关键字等机制,解决多线程环境下的数据可见性、原子性和有序性问题。不同于常规摘要的简述方式,本摘要将直接概述文章的核心内容,为读者提供一个清晰的学习路径。 ####
90 2
|
8月前
|
Java
JAVA并发编程系列(9)CyclicBarrier循环屏障原理分析
本文介绍了拼多多面试中的模拟拼团问题,通过使用 `CyclicBarrier` 实现了多人拼团成功后提交订单并支付的功能。与之前的 `CountDownLatch` 方法不同,`CyclicBarrier` 能够确保所有线程到达屏障点后继续执行,并且屏障可重复使用。文章详细解析了 `CyclicBarrier` 的核心原理及使用方法,并通过代码示例展示了其工作流程。最后,文章还提供了 `CyclicBarrier` 的源码分析,帮助读者深入理解其实现机制。
|
8月前
|
Java 开发者
深入探索Java中的并发编程
本文将带你领略Java并发编程的奥秘,揭示其背后的原理与实践。通过深入浅出的解释和实例,我们将探讨Java内存模型、线程间通信以及常见并发工具的使用方法。无论是初学者还是有一定经验的开发者,都能从中获得启发和实用的技巧。让我们一起开启这场并发编程的奇妙之旅吧!
59 5