Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。

常用函数: 
信号量的构造函数 
非公平:

public Semaphore(int permits);//permits就是允许同时运行的线程数目

公平(获得锁的顺序与线程启动顺序有关):

public Semaphore(int permits,boolean fair);//permits就是允许同时运行的线程数目

创建一个信号量

Semaphore semaphore = new Semaphore(2);

从信号量中获取一个许可

semaphore.acquire();

释放一个许可(在释放许可之前,必须先获获得许可。)

semaphore.release();

尝试获取一个许可,若获取成功返回true,若获取失败返回false

semaphore.tryAcquire();

所有函数:

// 创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits)
// 创建具有给定的许可数和给定的公平设置的 Semaphore。
Semaphore(int permits, boolean fair) // 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void acquire()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
void acquire(int permits)
// 从此信号量中获取许可,在有可用的许可前将其阻塞。
void acquireUninterruptibly()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
void acquireUninterruptibly(int permits)
// 返回此信号量中当前可用的许可数。
int availablePermits()
// 获取并返回立即可用的所有许可。
int drainPermits()
// 返回一个 collection,包含可能等待获取的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待获取的线程的估计数目。
int getQueueLength()
// 查询是否有线程正在等待获取。
boolean hasQueuedThreads()
// 如果此信号量的公平设置为 true,则返回 true。
boolean isFair()
// 根据指定的缩减量减小可用许可的数目。
protected void reducePermits(int reduction)
// 释放一个许可,将其返回给信号量。
void release()
// 释放给定数目的许可,将其返回到信号量。
void release(int permits)
// 返回标识此信号量的字符串,以及信号量的状态。
String toString()
// 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
boolean tryAcquire()
// 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。
boolean tryAcquire(int permits)
// 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
// 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。
boolean tryAcquire(long timeout, TimeUnit unit)

代码实例: 
假设有10个人在银行办理业务,只有2个工作窗口,代码实现逻辑如下

public class SemaphoreDemo {

    // 排队总人数(请求总数)
public static int clientTotal = 10; // 可同时受理业务的窗口数量(同时并发执行的线程数)
public static int threadTotal = 2; public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final int count = i;
executorService.execute(() -> {
try {
semaphore.acquire(1);
resolve(count);
semaphore.release(2);
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
} private static void resolve(int i) throws InterruptedException {
log.info("服务号{},受理业务中。。。", i);
Thread.sleep(2000);
}
}

输出结果:

21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号0,受理业务中。。。
21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号1,受理业务中。。。
21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号3,受理业务中。。。
21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号2,受理业务中。。。
21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号5,受理业务中。。。
21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号4,受理业务中。。。
21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号6,受理业务中。。。
21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号7,受理业务中。。。
21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号9,受理业务中。。。
21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号8,受理业务中。。。

从输出结果可以看出,每隔两秒,有两个线程被执行

原文链接:https://blog.csdn.net/yuruixin_china/article/details/82084946

Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。
常用函数: 信号量的构造函数 非公平:
public Semaphore(int permits);//permits就是允许同时运行的线程数目1公平(获得锁的顺序与线程启动顺序有关):
public Semaphore(int permits,boolean fair);//permits就是允许同时运行的线程数目1创建一个信号量
Semaphore semaphore = new Semaphore(2);1从信号量中获取一个许可
semaphore.acquire();1释放一个许可(在释放许可之前,必须先获获得许可。)
semaphore.release();1尝试获取一个许可,若获取成功返回true,若获取失败返回false
semaphore.tryAcquire();1所有函数:
// 创建具有给定的许可数和非公平的公平设置的 Semaphore。Semaphore(int permits)// 创建具有给定的许可数和给定的公平设置的 Semaphore。Semaphore(int permits, boolean fair)
// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。void acquire()// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。void acquire(int permits)// 从此信号量中获取许可,在有可用的许可前将其阻塞。void acquireUninterruptibly()// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。void acquireUninterruptibly(int permits)// 返回此信号量中当前可用的许可数。int availablePermits()// 获取并返回立即可用的所有许可。int drainPermits()// 返回一个 collection,包含可能等待获取的线程。protected Collection<Thread> getQueuedThreads()// 返回正在等待获取的线程的估计数目。int getQueueLength()// 查询是否有线程正在等待获取。boolean hasQueuedThreads()// 如果此信号量的公平设置为 true,则返回 true。boolean isFair()// 根据指定的缩减量减小可用许可的数目。protected void reducePermits(int reduction)// 释放一个许可,将其返回给信号量。void release()// 释放给定数目的许可,将其返回到信号量。void release(int permits)// 返回标识此信号量的字符串,以及信号量的状态。String toString()// 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。boolean tryAcquire()// 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。boolean tryAcquire(int permits)// 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。boolean tryAcquire(int permits, long timeout, TimeUnit unit)// 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。boolean tryAcquire(long timeout, TimeUnit unit)1234567891011121314151617181920212223242526272829303132333435363738394041代码实例: 假设有10个人在银行办理业务,只有2个工作窗口,代码实现逻辑如下
package com..concurrency.yuxin.demo;
import lombok.extern.slf4j.Slf4j;import org.joda.time.DateTime;import org.joda.time.format.DateTimeFormat;import org.joda.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;
@Slf4jpublic class SemaphoreDemo {
    // 排队总人数(请求总数)    public static int clientTotal = 10;
    // 可同时受理业务的窗口数量(同时并发执行的线程数)    public static int threadTotal = 2;

public static void main(String[] args) throws Exception {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i < clientTotal; i++) {            final int count = i;            executorService.execute(() -> {                try {                    semaphore.acquire(1);                    resolve(count);                    semaphore.release(2);                } catch (Exception e) {                    log.error("exception", e);                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();    }
    private static void resolve(int i) throws InterruptedException {        log.info("服务号{},受理业务中。。。", i);        Thread.sleep(2000);    }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849输出结果:
21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号0,受理业务中。。。21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号1,受理业务中。。。21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号3,受理业务中。。。21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号2,受理业务中。。。21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号5,受理业务中。。。21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号4,受理业务中。。。21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号6,受理业务中。。。21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号7,受理业务中。。。21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号9,受理业务中。。。21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服务号8,受理业务中。。。12345678910从输出结果可以看出,每隔两秒,有两个线程被执行--------------------- 版权声明:本文为CSDN博主「yuruixin_china」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/yuruixin_china/article/details/82084946

Semaphore的简介及应用场景的更多相关文章

  1. [转帖]kafka入门:简介、使用场景、设计原理、主要配置及集群搭建

    kafka入门:简介.使用场景.设计原理.主要配置及集群搭建 http://www.aboutyun.com/thread-9341-1-1.html 还没看完 感觉挺好的. 问题导读: 1.zook ...

  2. kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)

    问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状 ...

  3. 开放数据接口 API 简介与使用场景、调用方法

    此文章对开放数据接口 API 进行了功能介绍.使用场景介绍以及调用方法的说明,供用户在使用数据接口时参考之用. 在给大家分享的一系列软件开发视频课程中,以及在我们的社区微信群聊天中,都积极地鼓励大家开 ...

  4. RabbitMQ 简介以及使用场景

    目录 一. RabbitMQ 简介 二. RabbitMQ 使用场景 1. 解耦(为面向服务的架构(SOA)提供基本的最终一致性实现) 2. 异步提升效率 3. 流量削峰 三. 引入消息队列的优缺点 ...

  5. 浅谈nginx简介和应用场景

    简介 nginx是一款轻量级的web服务器,它是由俄罗斯的程序设计师伊戈尔·西索夫所开发. nginx相比于Tomcat性能十分优秀,能够支撑5w的并发连接(而Tomcat只能支撑200-400),并 ...

  6. 中间件 | kafka简介、使用场景、设计原理、主要配置及集群搭建

    开源Java学习 公众号 一.入门 1.简介 Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性 ...

  7. Redis简介,应用场景,优势

    Redis简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化 ...

  8. 01 . etcd简介原理,应用场景及部署,简单使用

    etcd简介 Etcd是CoreOS团队于2013年6月发起的开源项目,他的目标是构建一个高可用的分布式键值(key-value)数据库,etcd内部采用raft协议作为一致性算法,etcd基于Go语 ...

  9. spark第一篇--简介,应用场景和基本原理

    摘要: spark的优势:(1)图计算,迭代计算(2)交互式查询计算 spark特点:(1)分布式并行计算框架(2)内存计算,不仅数据加载到内存,中间结果也存储内存 为了满足挖掘分析与交互式实时查询的 ...

随机推荐

  1. eclipse集成maven(四)

    一.配置maven 打开Window-Preference-Maven,我们可以看到,默认是使用Eclipse的,不是我们要的maven,可以在Installations中,点击"Add&q ...

  2. 每天一道Rust-LeetCode(2019-06-10)

    每天一道Rust-LeetCode(2019-06-02) Z 字形变换 坚持每天一道题,刷题学习Rust. 题目描述 https://leetcode-cn.com/problems/simplif ...

  3. AWS云部署项目——数据库与服务器

    1.连接数据库 选择服务RDS,进入后点击数据库实例,在之前建好的数据库内进行操作 首先是安全组,类似于aws云上的防火墙一样的东西,先设置好公开性,安全组置为default(就是尽量避免测试时访问阻 ...

  4. web框架--tornado自定义分页

    1.tornado_main.py #!/usr/bin/env python # -*- coding: utf-8 -*- import tornado.web import tornado.io ...

  5. [RN] 使用 Genymotion 导致 ” Genymotion 已连接,但无法访问互联网 “ 的错误

    使用 Genymotion 导致 Genymotion 已连接,但无法访问互联网 的错误 先把要点 放前面: 网络二 一定要设置 桥接模式 网上很多文章都是设置为 NAT,笔者均失败! 笔者使用的An ...

  6. nowcoder911J 异或的路径

    题目链接 题意 给出一棵树,每条边有边权.求\(\sum\limits_{i=1}^n{f(i,j)}\),\(f(i,j)\)表示从i到j路径的异或和. 思路 \(g_i\)表示从根到\(i\)的异 ...

  7. divide two numbers using + opertor

    package testpacknm; import java.util.Scanner; public class testcnm { public static void main(String[ ...

  8. pytorch的state_dict()拷贝问题

    先说结论,model.state_dict()是浅拷贝,返回的参数仍然会随着网络的训练而变化.应该使用deepcopy(model.state_dict()),或将参数及时序列化到硬盘. 再讲故事,前 ...

  9. js原型和原型链,以及__proto__、prototype属性

    __proto__和prototype属性: 1.__proto__属性: 在JS里,万物皆对象(函数是对象.原型也是对象...).对象都具有属性__proto__,这个属性会指向该对象的原型. 2. ...

  10. Qt 窗口操作函数(置顶、全屏,最大化最小化按钮设置等)

    一.窗口置顶 与 取消置顶 void MainWindow::on_windowTopButton_clicked() { if (m_flags == NULL) { m_flags = windo ...