`

java多线程之Semaphore使用

阅读更多

        本文将介绍用来控制资源同时访问个数的Semaphore工具类,然后采用Semaphore给出一个泊车的实例,最后给出Semaphore和CountDownLatch的几点比较。

一. Semaphore工具类介绍

/**
 * A counting semaphore.  Conceptually, a semaphore maintains a set of
 * permits.  Each {@link #acquire} blocks if necessary until a permit is
 * available, and then takes it.  Each {@link #release} adds a permit,
 * potentially releasing a blocking acquirer.
 * However, no actual permit objects are used; the <tt>Semaphore</tt> just
 * keeps a count of the number available and acts accordingly.
 *
 * <p>Semaphores are often used to restrict the number of threads than can
 * access some (physical or logical) resource.
 */

        从Semaphore的注释中可以看出如下几点:
        1.从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
        2. Semaphore并不使用实际的许可对象,Semaphore 只对可用许可进行计数,并采取相应的行动。

        3.Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

        Semaphore中定义了一个内部类Sync,该类继承AbstractQueuedSynchronizer。从代码中可以看出,Semaphore的方法基本上都调用了Sync的方法来实现。Smaphore还提供了公平和非公平的两种方式。

        Semaphore工具类相关的类图如下:

 

二. Semaphore工具类的使用案例

        下面给出的示例模拟30辆车去泊车,而车位有10个的场景。当车位满时,出来一辆车,才能有一辆车进入停车。

Car.java

package my.concurrent.semaphore;

import java.util.concurrent.Semaphore;

public class Car implements Runnable {

    private final Semaphore parkingSlot;
    private int carNo;

    /**
     * @param parkingSlot
     * @param carName
     */
    public Car(Semaphore parkingSlot, int carNo) {
        this.parkingSlot = parkingSlot;
        this.carNo = carNo;
    }

    public void run() {
        try {
            parkingSlot.acquire();
            parking();
            sleep(300);
            parkingSlot.release();
            leaving();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void parking() {
        System.out.println(String.format("%d号车泊车", carNo));
    }

    private void leaving() {
        System.out.println(String.format("%d号车离开车位", carNo));
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ParkingCars.java

package my.concurrent.semaphore;

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

public class ParkingCars {

    private static final int NUMBER_OF_CARS = 30;
    private static final int NUMBER_OF_PARKING_SLOT = 10;

    public static void main(String[] args) {
        /*
         * 采用FIFO, 设置true
         */
        Semaphore parkingSlot = new Semaphore(NUMBER_OF_PARKING_SLOT, true);
        ExecutorService service = Executors.newCachedThreadPool();
        for (int carNo = 1; carNo <= NUMBER_OF_CARS; carNo++) {
            service.execute(new Car(parkingSlot, carNo));
        }
        sleep(3000);
        service.shutdown();
        /*
         * 输出还有几个可以用的资源数
         */
        System.out.println(parkingSlot.availablePermits() + " 个停车位可以用!");
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

        运行结果:

4号车泊车
6号车泊车
8号车泊车
2号车泊车
10号车泊车
3号车泊车
5号车泊车
11号车泊车
1号车泊车
9号车泊车
4号车离开车位
13号车泊车
8号车离开车位
7号车泊车
2号车离开车位
15号车泊车
10号车离开车位
17号车泊车
6号车离开车位
12号车泊车
3号车离开车位
16号车泊车
14号车泊车
18号车泊车
11号车离开车位
5号车离开车位
1号车离开车位
19号车泊车
20号车泊车
9号车离开车位
13号车离开车位
21号车泊车
22号车泊车
7号车离开车位
15号车离开车位
23号车泊车
17号车离开车位
24号车泊车
12号车离开车位
25号车泊车
26号车泊车
14号车离开车位
27号车泊车
28号车泊车
16号车离开车位
20号车离开车位
29号车泊车
18号车离开车位
30号车泊车
19号车离开车位
21号车离开车位
23号车离开车位
22号车离开车位
26号车离开车位
24号车离开车位
28号车离开车位
30号车离开车位
25号车离开车位
27号车离开车位
29号车离开车位
10 个停车位可以用!

 

三. Semaphore vs. CountDownLatch

相同点:   
        两者都是用于线程同步的工具类,都通过定义了一个继承AbstractQueuedSynchronizer的内部类Sync来实现具体的功能。

不同点:
        1.Semaphore提供了公平和非公平两种策略, 而CountDownLatch则不具备。
        2.CountDownLatch: 一个或者是一部分线程,等待另外一部线程都完成操作。
           Semaphorr:维护一个许可集.通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

        3.CountDownLatch中计数是不能被重置的。CountDownLatch适用于一次同步。当使用CountDownLatch时,任何线程允许多次调用countDown()。那些调用了await()方法的线程将被阻塞,直到那些没有被阻塞线程调用countDown()使计数到达0为止。
        Semaphore允许线程获取许可, 未获得许可的线程需要等待.这样防止了在同一时间有太多的线程执行.Semaphore的值被获取到后是可以释放的,并不像CountDownLatch那样一直减到0。

        4.使用CountDownLatch时,它关注的一个线程或者多个线程需要在其它在一组线程完成操作之后,在去做一些事情。比如:服务的启动等。使用Semaphore时,它关注的是某一个资源最多同时能被几个线程访问。

 

文章来源:http://mouselearnjava.iteye.com/blog/1921468

  • 大小: 26.3 KB
分享到:
评论

相关推荐

    Java多线程Semaphore工具的使用详解.rar

    Java多线程Semaphore工具的使用详解.rar

    java线程并发semaphore类示例

    Java 5.0里新加了4个协调线程间进程的同步装置,它们分别是Semaphore, CountDownLatch, CyclicBarrier和Exchanger,本例主要介绍Semaphore,Semaphore是用来管理一个资源池的工具,可以看成是个通行证

    JAVA 多线程之信号量(Semaphore)实例详解

    主要介绍了JAVA 多线程之信号量(Semaphore)实例详解的相关资料,需要的朋友可以参考下

    JAVA多线程--信号量(Semaphore)_.docx

    JAVA多线程--信号量(Semaphore)_.docx

    Java多线程之并发工具类

     1)CountDownLatch(同步倒数计数器:等待多线程(或者多步骤)完成)  2)CyclicBarrier(循环屏障:同步屏障)  3)Semaphore(信号量:控制并发进程数)  主要参考资料:java并发编程的艺术、Java并发——...

    个人总结的深入java多线程开发

    看完《think in java》多线程章节,自己写的多线程文档,还结合了其他的相关网络资料。 线程 一. 线程池 1)为什么要使用线程池 2 2)一个具有线程池的工作队列 3 3)使用线程池的风险: 4 4)有效使用线程池的原则 5...

    2023年最新Java高并发多线程面试题

    适用人群:适合想了解或学习高并发多线程的 IT 学生、开发人员、研究人员以及使用Java多线程进行开发的任何人。 能学到什么:常见Java高并发多线程面试问题及在相关场景下如何处理和解决这些问题。 阅读建议:通过...

    详解java多线程的同步控制

    目录线程安全 Thread Safety重入锁 ReentrantLock读写锁 ReadWriteLock倒计数器 CountDownLatch循环栅栏 CyclicBarrier信号量 Semaphore 线程安全 Thread Safety JMM JMM(Java Memory Model)是一种基于计算机内存...

    92道Java多线程与并发面试题含答案(很全)

    Java并发编程的核心概念包括: 线程(Thread):线程是程序执行流的最小单元。...原子操作(Atomic Operations):原子操作是不可中断的操作,即在多线程环境中,这些操作要么完全执行,要么完全不执行。

    Java信号量Semaphore

     Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。  Semaphore实现的功能类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够...

    JAVA高质量并发详解,多线程并发深入讲解

    本书全面解析了Java并发编程的核心概念、原理和实践,帮助读者深入理解多线程并发编程的精髓,提升编程能力和系统性能。 书中首先介绍了并发编程的基础知识,包括线程的基本概念、线程的生命周期、线程安全等问题。...

    【2018最新最详细】并发多线程教程

    【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗...

    php多进程框架-模拟java多线程接口simple-fork-php.zip

    SimpleFork提供一套类似于JAVA多线程的进程控制接口,提供回收、同步、互斥、通信等方案,开发者可以关注业务问题,不需要过多考虑进程控制。 引入 composer require jenner/simple_fork require path/to/...

    带你看看Java的锁(二)-Semaphore

    带你看看Java的锁-Semaphore前言简介使用源码分析类结构图SyncNonfairSyncFairSyncSemaphore 构造函数Semaphore 成员方法获取释放总结 前言 简介 Semaphore 中文称信号量,它和ReentrantLock 有所区别,...

    JUC多线程学习个人笔记

    JUC(Java Util Concurrent)是Java中用于并发编程的工具包,提供了一组接口和类,用于处理多线程和并发操作。JUC提供了一些常用的并发编程模式和工具,如线程池、并发集合、原子操作等。 JUC的主要特点包括: ...

    Java多线程同步器代码详解

    主要介绍了Java多线程同步器代码详解,文章分别介绍了是CountDownLatch,Semaphore,Barrier和Exchanger以及其相关代码示例,具有一定参考价值,需要的朋友可以了解下。

    迅雷笔试题java-concurrent_download:Java多线程并发下载器,支持断点下载(手写不限速的迷你版迅雷)

    Java并发编程:03-多线程并发下载器, 支持断点下载(手写不限速的迷你版迅雷) 主要是最近学习完一些初级的并发知识, 所以想使用这些知识做一个小小工具, 巩固一下知识点, 然后就想到了多线程并发下载文件的这个小工具...

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用 CountDownLatch、CyclicBarrier、Semaphore这些线程协作工具类是基于AQS的,看完这篇博客后可以去看下面这篇博客,了解它们是如何实现的。 Java并发...

    多线程控制的三大安全类封装

    多线程控制的三大安全类:CountDownLatch、CyclicBarrier、Semaphore,这工具包将其封装,可以让初学者更容易学习以及让开发者更容易调用,不需要自己重新编写核心代码。具体事例在源码中。

    Java并发编程相关技术使用案例

    1、本资源包含并发编程基础知识的使用案例,包括:线程创建、Synchronized和Reentrantlock锁的使用、线程安全问题演示、Condition的应用、CountDownLatch的应用、Cyclicbarrier的应用、Semaphore的应用、线程池的...

Global site tag (gtag.js) - Google Analytics