Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。自从5.0开始,jdk在java.util.concurrent包里提供了Semaphore 的官方实现,因此大家不需要自己去实现Semaphore。

下面的类使用信号量控制对内容池的访问:

import java.util.concurrent.Semaphore;

class Pool {

private static final int MAX_AVAILABLE = 100;

private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);

public Object getItem() throws InterruptedException {

available.acquire(); // 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断

return getNextAvailableItem();

}

public void putItem(Object x) {

if (markAsUnused(x))

available.release(); // 释放一个许可,将其返回给信号量

}

// 仅作示例参考,非真实数据

protected Object[] items = null;

protected boolean[] used = new boolean[MAX_AVAILABLE];

protected synchronized Object getNextAvailableItem() {

for (int i = 0; i < MAX_AVAILABLE; ++i) {

if (!used[i]) {

used[i] = true;

return items[i];

}

}

return null;

}

protected synchronized boolean markAsUnused(Object item) {

for (int i = 0; i < MAX_AVAILABLE; ++i) {

if (item == items[i]) {

if (used[i]) {

used[i] = false;

return true;

} else

return false;

}

}

return false;

}

}

虽然JDK已经提供了相关实现,但是还是很有必要去熟悉如何使用Semaphore及其背后的原理。

做一个简单的Semaphore实现:

class SemaphoreTest {

private boolean signal = false;

public synchronized void take() {

this.signal = true;

this.notify();

}

public synchronized void release() throws InterruptedException {

while (!this.signal)

wait();

this.signal = false;

}

}

使用这个semaphore可以避免错失某些信号通知。用take方法来代替notify,release方法来代替wait。如果某线程在调用release等待之前调用take方法,那么调用release方法的线程仍然知道take方法已经被某个线程调用过了,因为该Semaphore内部保存了take方法发出的信号。而wait和notify方法就没有这样的功能。

可计数的Semaphore:

class SemaphoreTest {

private int signals = 0;

public synchronized void take() {

this.signals++;

this.notify();

}

public synchronized void release() throws InterruptedException {

while (this.signals == 0)

wait();

this.signals--;

}

}

Semaphore上限:

class SemaphoreTest {

private int signals = 0;

private int bound = 0;

public SemaphoreTest(int upperBound) {

this.bound = upperBound;

}

public synchronized void take() throws InterruptedException {

while (this.signals == bound)

wait();

this.signals++;

this.notify();

}

public synchronized void release() throws InterruptedException {

while (this.signals == 0)

wait();

this.signals--;

this.notify();

}

}

当已经产生的信号数量达到了上限,take方法将阻塞新的信号产生请求,直到某个线程调用release方法后,被阻塞于take方法的线程才能传递自己的信号。

把Semaphore当锁来使用:

当信号量的数量上限是1时,Semaphore可以被当做锁来使用。通过take和release方法来保护关键区域。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

java信号量源代码_Java信号量Semaphore原理及代码实例相关推荐

  1. java 页面查询_JAVA页面浏览量查询api调用代码实例

    代码描述:基于JAVA页面浏览量查询api调用代码实例 接口地址:http://www.juhe.cn/docs/api/id/51 1.[代码][Java]代码 import java.io.Buf ...

  2. java实现微博_java实现的新浪微博分享代码实例

    weibo.java @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstan ...

  3. java map类型转换_Java string类型转换成map代码实例

    背景:有时候string类型的数据取出来是个很标准的key.value形式,通过Gson的可以直接转成map 使用方式: Gson gson = new Gson(); Map map = new H ...

  4. JAVA 油站管理系统_基于JAVA的全国加油站[实时油价]接口调用代码实例

    代码描述:基于JAVA的全国加油站[实时油价]接口调用代码实例 接口地址:https://www.juhe.cn/docs/api/id/7 1.[代码][Java]代码 import java.io ...

  5. 【编程实践】Raft 算法的原理 go代码实例

    文章目录 Raft 算法的原理 & go代码实例 Raft 算法的原理 使用 Go 语言实现的简单 Raft 算法示例 Raft 算法的原理 & go代码实例 Raft 算法的原理 R ...

  6. c语言滚动字幕的原理编程,c#中通过Graphics.DrawString实现滚动字幕的原理和代码实例...

    c#中通过Graphics.DrawString实现滚动字幕的原理和代码实例 在c#中其实滚动屏幕的实现很简单,只需要用到Graphics.DrawString方法. Graphics.DrawStr ...

  7. 直播api接口java_基于JAVA的电视台直播节目时间表api调用代码实例

    代码描述:基于JAVA的电视台直播节目时间表api调用代码实例 接口地址:http://www.juhe.cn/docs/api/id/129 1.[代码][Java]代码 import java.i ...

  8. java 获取邮编_基于JAVA的根据地名查邮编api调用代码实例

    代码描述:基于JAVA的根据地名查邮编api调用代码实例 接口地址:http://www.juhe.cn/docs/api/id/66 1.[代码][Java]代码 import java.io.Bu ...

  9. 获得周公解梦数据接口java_基于JAVA的免费周公解梦接口调用代码实例

    代码描述:基于JAVA的免费周公解梦接口调用代码实例 接口地址:http://www.juhe.cn/docs/api/id/64 1.[代码][Java]代码 import java.io.Buff ...

最新文章

  1. 不会还有人不会配置LLDP链路层发现协议吧?
  2. CentOS 6.7构建 OpenResty(Nginx)+PHP 7(php-fpm)+MySQL5.7 运行环境
  3. 启动万维网发布服务(W3SVC)
  4. php html登陆逻辑,保持演示文稿(HTML)和逻辑(PHP)分开
  5. MAC安装mysql和navicat
  6. Javascript第五章改变CSS样式节点两种方法,制作导航背景切换效果第十课
  7. python正则表达式快速入门_Python 正则表达式入门
  8. 某地环境空气质量分析(1)
  9. 你不知道的JavaScript(上卷)- - 书本知识点记录
  10. 木瓜移动跨境行业一周咨讯:字节跳动旗下Fanno欧洲上线、亚马逊中国黑五战绩优秀
  11. python爬虫脚本 初级入门爬虫英雄联盟所有皮肤_用Python爬取英雄联盟(lol)全部皮肤...
  12. 关于LVGL下物理按键的使用
  13. Codeforces 300D Painting Square dp
  14. 网易有数BI在数据可视化领域的优势地位因何受到挑战?
  15. C语言新手记:相邻数对
  16. Java-设计模式之单例模式
  17. JavaScript中递归函数
  18. 如何从高德获取地铁数据
  19. M103: Basic Cluster Administration chapter 3 Sharding学习记录
  20. Windows UI改造-任务栏全透明、桌面数字时钟、息屏显示数字时钟

热门文章

  1. jquery读取json文件跨域_跨域方法的若干种方式
  2. log4j mysql 异步_spring boot:配置druid数据库连接池(开启sql防火墙/使用log4j2做异步日志/spring boot 2.3.2)...
  3. php短链接api,PHP通过调用新浪API生成t.cn格式短网址链接的方法详解
  4. dnf新起号怎么才不出人脸_DNF玩家花8千买号,还不到1年,眼前的一幕让他目瞪口呆...
  5. Blazor UI事件和渲染
  6. Newbe.McrMirror 1.1.6 发布,助您全速下载 mssql docker 镜像
  7. 使用Entity Framework Core,Swagger和Postman创建ASP.NET Core Web API的分步指南
  8. eureka常见错误
  9. oracle定时向mysql取数据_Oracle中通过Job实现定时同步两个数据表之间的数据
  10. android手机常用功能,Windows Phone 7/Android手机常用功能对比