Java并发编程信号量Semapher

 更新时间:2022年04月15日 16:24:59   作者:派大大大星   
这篇文章主要介绍了Java并发编程信号量Semapher,Semapher信号量也是Java中的一个同步器,下文关于信号量Semapher的更多内容介绍,需要的小伙伴可以参考下面文章

Semapher信号量也是Java中的一个同步器,与CountDownLatch和CycleBarrier不同的是,它内部的计数器是递增的,并且在一开始初始化Semaphoer时可以指定一个初始值,但是并不需要知道需要同步的线程个数,而是在需要同步的地方调用acquire方法时指定需要同步的线程个数。

我们通过下面一个例子来看一下Semapher效果:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    private static Semaphore semaphore = new Semaphore(0);
    public static void main(String[] args) throws InterruptedException{
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        semaphore.acquire(2);
        System.out.println("all child thread over!");
        executorService.shutdown();

    }
}

image.png

如上代码首先创建了一个信号量实例,构造函数的入参为0,说明当前信号量计数器的值为0。然后,main函数向线程池添加两个线程任务,在每个线程内部调用信号量的acquire方法,传参为2说明调用acquire方法的线程会一直阻塞,知道信号量的技术变为2才会返回。如果构造Semaphore时,传递的参数为N,并在M个线程中调用了该信号量的release方法,那么在调用acquire使M个线程同步时传递的参数应该是M+N。

下面举例子来模拟CycliBarrier复用的功能,代码如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class Semaphoer {

    private static Semaphore semaphore = new Semaphore(0);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "A task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "A task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        semaphore.acquire(2);
        System.out.println("task A is over");
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "B task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread() + "B task over");
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        semaphore.acquire(2);
        System.out.println("task B is over");
        executorService.shutdown();

    }
}

image.png

如上代码首先将线程A和线程B加入到线程池。主线程执行代码(1)后被阻塞。线程A和线程B调用release方法后信号量的值变为了2,这时候主线程的aquire方法会在获取到2个信号量后返回(返回后当前信号量值为0)。然后主线程添加线程C和线程D到线程池,之后主线程执行代码(2)后被阻塞(因为主线程要获取2个信号量,而当前信号量个数为0)。当线程C和线程D执行完release 方法后,主线程才返回。从本例子可以看出,Semaphore 在某种程度上实现了CyclicBarrier 的复用功能。

到此这篇关于Java并发编程信号量Semapher的文章就介绍到这了,更多相关Java Semapher内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot定时任务两种(Spring Schedule 与 Quartz 整合 )实现方法

    SpringBoot定时任务两种(Spring Schedule 与 Quartz 整合 )实现方法

    本篇文章主要介绍了SpringBoot定时任务两种(Spring Schedule 与 Quartz 整合 )实现方法,详细的介绍了Spring Schedule 与 Quartz 整合的两种方法,有兴趣的可以了解一下。
    2017-03-03
  • AJAX省市区三级联动下拉菜单(java版)

    AJAX省市区三级联动下拉菜单(java版)

    这篇文章主要介绍了AJAX省市区三级联动下拉菜单(java版)的相关资料,需要的朋友可以参考下
    2016-01-01
  • 浅谈Java基于Consul创建分布式锁

    浅谈Java基于Consul创建分布式锁

    这篇文章主要介绍了浅谈基于Consul创建分布式锁,Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置Consul是分布式的、高可用的、可横向扩展的,需要的朋友可以参考下
    2023-07-07
  • Java树形结构递归查询方式

    Java树形结构递归查询方式

    文章介绍了Java中实现树形结构递归查询的方法,首先找出所有的根节点,然后通过循环遍历根节点,找到每个根节点的子节点,最终构建完整的树形结构,这是一种有效的递归查询思路,适用于需要层次化展示数据的场景
    2024-12-12
  • Java新API的时间格式化

    Java新API的时间格式化

    这篇文章主要介绍了Java新API的时间格式化,新的时间API的时间格式化由java.time.format.DateTimeFormatter负责,更多相关资料需要的小伙伴可以参考一下
    2022-05-05
  • java实现获取安卓设备里已安装的软件包

    java实现获取安卓设备里已安装的软件包

    本文给大家介绍的是如何获取设备中已经安装的应用软件包的代码,其核心方法原理很简单,我们通过Android中提供的PackageManager类,来获取手机中安装的应用程序信息
    2015-10-10
  • Java8中Lambda表达式的理解与应用

    Java8中Lambda表达式的理解与应用

    Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,下面这篇文章主要给大家介绍了关于Java8中Lambda表达式的相关资料,需要的朋友可以参考下
    2022-02-02
  • java中Lamda表达式讲解

    java中Lamda表达式讲解

    本文详细讲解了java中的Lamda表达式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • Mybatis多线程下如何使用Example详解

    Mybatis多线程下如何使用Example详解

    这篇文章主要给大家介绍了关于Mybatis多线程下如何使用Example的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Mybatis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • struts2中simple主题下<s:fieldError>标签默认样式的移除方法

    struts2中simple主题下<s:fieldError>标签默认样式的移除方法

    这篇文章主要给大家介绍了关于struts2中simple主题下<s:fieldError>标签默认样式的移除方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-10-10

最新评论