Java并发编程信号量Semapher

Java并发编程信号量Semapher攻略

在Java并发编程中,信号量(Semaphore)是一种用于控制并发线程数量的工具,大多用于控制对共享资源的访问,通过信号量的控制,可以实现线程之间的协作与资源控制。

信号量(Semaphore)的概念及使用方法

信号量(Semaphore)是一个经典的多线程同步控制工具,它用于控制同时访问某个资源的线程数量,通过指定信号量的许可数量,我们可以控制同时访问共享资源的线程数量。

具体来说,Semaphore可以分为两种类型:

  • 二元信号量(Binary Semaphore):只具有两种状态,1表示可用,0表示不可用,通常将其用于控制对临界区的访问;
  • 计数信号量(Counting Semaphore):具有一定数量的状态,我们可以通过调用release()方法增加信号量,调用acquire()方法减少信号量。

Semaphore的使用方法如下:

Semaphore sem = new Semaphore(permits); // 构造Semaphore对象,permits表示初始信号量的数量
sem.acquire(); // 获取信号量,如果信号量不够的话就一直等待
...
sem.release(); // 释放信号量

示例一:Semaphore控制线程并发访问

下面的示例用两个线程并发访问同一个共享资源,通过Semaphore控制线程的并发访问数量:

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(2); // 构造Semaphore对象,permit数量为2
        ExecutorService executorService = Executors.newCachedThreadPool(); // 构造线程池

        for (int i = 1; i <= 10; i++) { // 启动10个线程
            executorService.execute(() -> {
                try {
                    semaphore.acquire(); // 获取Semaphore许可
                    System.out.println(Thread.currentThread().getName()+" got the permit.");
                    Thread.sleep(2000); // 等待2s
                    semaphore.release(); // 释放Semaphore许可
                    System.out.println(Thread.currentThread().getName()+" released the permit.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        executorService.shutdown(); // 关闭线程池
    }
}

运行结果如下:

pool-1-thread-1 got the permit.
pool-1-thread-2 got the permit.
pool-1-thread-1 released the permit.
pool-1-thread-3 got the permit.
pool-1-thread-2 released the permit.
pool-1-thread-4 got the permit.
pool-1-thread-3 released the permit.
pool-1-thread-5 got the permit.
pool-1-thread-4 released the permit.
pool-1-thread-6 got the permit.
pool-1-thread-5 released the permit.
pool-1-thread-7 got the permit.
pool-1-thread-6 released the permit.
pool-1-thread-8 got the permit.
pool-1-thread-7 released the permit.
pool-1-thread-10 got the permit.
pool-1-thread-9 got the permit.
pool-1-thread-10 released the permit.
pool-1-thread-9 released the permit.

可以看到,在Semaphore的控制下,每次只有两个线程能够同时访问共享资源,其他线程需要等待已经获取许可的线程释放许可后才能继续执行。

示例二:Semaphore模拟停车场

下面的示例用Semaphore模拟停车场系统,停车场只允许有限数量的车辆进入,超过限制的车辆需要等待其他车辆驶离后才能进入:

public class SemaphoreParkingDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(2); // 停车场只能同时容纳2辆汽车
        ExecutorService executorService = Executors.newCachedThreadPool(); // 构造线程池

        for (int i = 1; i <= 5; i++) { // 启动5辆汽车
            executorService.execute(() -> {
                try {
                    semaphore.acquire(); // 获取Semaphore许可
                    System.out.println(Thread.currentThread().getName() + " 进入了停车场。");
                    Thread.sleep(new Random().nextInt(1000)); // 随机停留1s以内的时间
                    semaphore.release(); // 释放Semaphore许可
                    System.out.println(Thread.currentThread().getName() + " 离开了停车场。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        executorService.shutdown(); // 关闭线程池
    }
}

运行结果如下:

pool-1-thread-1 进入了停车场。
pool-1-thread-2 进入了停车场。
pool-1-thread-2 离开了停车场。
pool-1-thread-3 进入了停车场。
pool-1-thread-4 进入了停车场。
pool-1-thread-1 离开了停车场。
pool-1-thread-3 离开了停车场。
pool-1-thread-5 进入了停车场。
pool-1-thread-4 离开了停车场。
pool-1-thread-5 离开了停车场。

可以看到,Semaphore实现了停车场的限流,只有2辆汽车能够同时进入停车场,其他的汽车需要等待前面的汽车离开才能进入。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程信号量Semapher - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)推荐

    实现SpringBoot中并发定时任务和动态定时任务,可以使用Spring框架提供的@Scheduled注解和Quartz定时任务框架。 并发定时任务的实现 (1) 引入依赖 在pom.xml文件中添加如下依赖: <dependency> <groupId>org.springframework.boot</groupId&gt…

    多线程 2023年5月17日
    00
  • 关于Java8 parallelStream并发安全的深入讲解

    关于Java8 parallelStream并发安全的深入讲解 Java 8引入的Stream API提供了一种非常方便和高效的处理集合的方式。parallelStream()方法可以使用多线程来利用CPU的多核执行计算。本文将深入讲解Java 8中parallelStream()的实现原理以及如何保证并发安全。 parallelStream() 并行流的实…

    多线程 2023年5月16日
    00
  • 基于rocketmq的有序消费模式和并发消费模式的区别说明

    基于RocketMQ的有序消费模式和并发消费模式的区别说明 1. 有序消费模式 在有序消费模式下,消息消费是按照消息的发送顺序依次进行的。具体实现方式是,消息生产者将消息发送到同一个Message Queue中,而Message Queue按照顺序将消息发送给Consumer进行消费。因此,在有序消费模式下,同一个Message Queue的消息一定会按照发…

    多线程 2023年5月17日
    00
  • C#线程队列用法实例分析

    C#线程队列用法实例分析 1. 什么是线程队列 线程队列指的是一种数据结构,它遵循“先进先出(FIFO)”的原则,即第一个入队的元素也会是第一个被出队的元素。在C#中,我们可以使用Queue<T>类来实现线程队列。 2. 线程队列的主要用途 线程队列常用于多线程编程中,以便按照一定顺序访问共享资源,避免数据竞争等多线程并发问题。 3. C#中线程…

    多线程 2023年5月16日
    00
  • Linux系统下Shell多线程编程的实例

    我来为您详细讲解一下在Linux系统下Shell多线程编程的实例攻略。 Shell多线程编程的实例攻略 1. Shell脚本实现多线程 在linux系统下,我们可以通过工具和bash本身的内置命令实现多线程编程。其中常用的工具包括:GNU Parallel和xargs命令。 使用GNU Parallel实现多线程: cat filelist | parall…

    多线程 2023年5月17日
    00
  • golang基于errgroup实现并发调用的方法

    Golang基于errgroup实现并发调用的方法 在Golang中,errgroup是一个非常好用的并发控制库,它允许我们创建一组goroutine并发执行一系列的任务并监控它们的运行情况。本文将介绍如何使用errgroup实现并发调用的方法。 一、准备工作 在使用errgroup前,我们需要先引入它的包: import "golang.org/…

    多线程 2023年5月17日
    00
  • 详解Java七大阻塞队列之SynchronousQueue

    详解Java七大阻塞队列之SynchronousQueue 简介 Java提供了七种不同类型的阻塞队列,SynchronousQueue是其中比较特殊的一种。它的特点是在插入元素时必须等待另外一个线程同时要移除这个元素,否则阻塞当前线程;同理,在移除元素时也必须等待另一个线程同时要插入这个元素,否则也会阻塞当前线程。这使得SynchronousQueue成为…

    多线程 2023年5月16日
    00
  • Java 多线程同步 锁机制与synchronized深入解析

    Java 多线程同步 锁机制与synchronized深入解析 在Java多线程编程中,为了保证线程安全,我们需要使用同步机制来避免多个线程同时访问共享资源造成数据不一致等问题。其中最常用的同步机制就是锁机制。 锁机制 锁机制就是控制多个线程访问共享资源的方式,一般来说,对于共享资源的访问,我们需要通过获取锁来限制只有一个线程可以访问,其他线程需要等待当前线…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部