Java核心知识点学习----线程中的Semaphore学习,公共厕所排队策略
1.什么是Semaphore?
A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire blocks if
necessary until a permit is available, and then takes it. Each release adds a permit, potentially releasing a
blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the
number available and acts accordingly.
Semaphores are often used to restrict the number of threads than can access some (physical or logical)
resource.
上面是官方给予该类的介绍,信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。
举个例子,公共厕所只有3个位子,有10个人要上厕所.一开始3个位都是空的,那么将有3个人先后占得坑,其它人只要在外面等待.如果有一个人上完厕所,然后等待中的7人中将有一个可以去上厕所.也有可能同时有两人OK,那么也将会同时有两人补位.简单说就是你必须有空位了,才能去上厕所.
上厕所的例子虽不雅观,但令人印象深刻,本来想举ATM机取钱的例子的,但意思一样,还是举上厕所吧.
Semaphore的作用就是控制位置的分配,一般情况下位置的分配是随机的,可以在实例化对象时设置规则进行排序.
2.实例
先看效果:

再来看代码:
package com.amos.concurrent; import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; /**
* @ClassName: SemaPhoreTest
* @Description: 线程通信中的"信号灯"
* @author: amosli
* @email:hi_amos@outlook.com
* @date Apr 25, 2014 12:06:22 AM
*/
public class SemaPhoreTest {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool(); final Semaphore semaphore=new Semaphore(3);
for(int i=0;i<10;i++){
threadPool.execute(new Runnable() {
public void run() {
try {
semaphore.acquire();//获取一个可用的permits
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("线程 " + Thread.currentThread().getName()+" 已进入. " + "目前已经有"+(3-semaphore.availablePermits())+" 个线程进入");
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程 "+Thread.currentThread().getName()+ " 即将离开...");
semaphore.release();//释放一个线程
System.out.println("线程 "+Thread.currentThread().getName()+ " 已离开. 当前有"+(3-semaphore.availablePermits())+"并发");
}
});
}
}
}
怎么保证是有序的?
上面的代码是不保证顺序的,如果要有个先后顺序,即FIFO,先进先出原则,有个排队,上厕所要排队,只需要将上面的代码改掉一行即可.
final Semaphore semaphore=new Semaphore(3, true);
这样就可以了,其它代码不变.效果如下图所示:

3.代码说明
1).如何创建Semaphore?
new Semaphore(3);//无序默认创建是无序的.
new Semaphore(3,true);//有序
2)如何获取一个"坑位"?
首先,程序会先检查,"坑"是否已经满了,如果没满,那么可以按需分配,具体代码如下:
try {semaphore.acquire();//获取一个可用的permits
} catch (Exception e) {
e.printStackTrace();
}
然后,分配完以后,将会把此坑位置为不可用了.
3)如何释放一个"坑位"?
semaphore.release();//释放一个线程
释放完成以后将会把此坑位置为可用的.
4.扩展--官方例子
For example, here is a class that uses a semaphore to control access to a pool of items:
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();
} // Not a particularly efficient data structure; just for demo protected Object[] items = ... whatever kinds of items being managed
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; // not reached
} 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;
} }
Java核心知识点学习----线程中的Semaphore学习,公共厕所排队策略的更多相关文章
- java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService
前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...
- Java核心知识点学习----使用Condition控制线程通信
一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A-> ...
- Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- Java面试知识点之线程篇(三)
前言:这里继续对java线程相关知识点进行总结,不能间断. 1.yield()方法 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执 ...
- Java面试知识点之线程篇(二)
前言:接上篇,这里继续对java线程相关知识点进行总结. 1.notify和notifyall的区别 notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象的 ...
- Java面试知识点之线程篇(一)
前言:在Java面试中,一定会遇到线程相关问题,因此笔者在这里总结Java中有关线程方面知识点,多数从网上得来(文中会贴出主要参考链接),有些也是笔者在面试中所遇到的问题,如有错误,请不吝指正.主要参 ...
- Java:类集框架中集合的学习
Java:类集框架中集合的学习 集合 Java:Set的学习 Set是类集框架中的集合类.集合是不按特定的方式排序,并且没有重复对象的一种类. Q:Set如何操作?Set中的不按特定方式排序是怎么排序 ...
随机推荐
- Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用
目录: 一.什么是Thrift? 1) Thrift内部框架一瞥 2) 支持的数据传输格式.数据传输方式和服务模型 3) Thrift IDL 二.Thrift的官方网站在哪里? 三.在哪里下载?需要 ...
- [入门]bower安装和使用
bower安装和使用 字数745 阅读10127 评论2 喜欢3 bower的安装 1,首先在我的系统 安装 nodejs.因为我的系统是windows,还需要安装msysgit,注意图二中的选项 m ...
- 四、Spring——Spring MVC
Spring MVC 1.Spring MVC概述 Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet负责截获请求并将其分配给响应的处理器处 ...
- 修改mongodb3.0副本集用户密码遇到的坑
最近公司对项目安全方面的问题很是重视,进行了多次各种安全漏洞的扫描,于是乎就扫到了mongodb弱口令的问题. 在项目部署初期,因为大家对这个都不是特别重视,大概是因为觉得反正是内网项目吧,所以mon ...
- PHP函数getopt详解
短参数 它返回一个包含命令行参数的数组.比如,要获得-a -b 和-c的值,可以这么做: $arguments = getopt("a:b:c:"); 可以用下面的方式运行脚本(有 ...
- (转)AVI文件格式解析+AVI文件解析工具
AVI文件解析工具下载地址:http://download.csdn.net/detail/zjq634359531/7556659 AVI(Audio Video Interleaved的缩写)是一 ...
- 每天一个 Linux 命令(7):mv命令
mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 1.命令格式: mv [选项] 源文件或目 ...
- iScroll.js和Swiper.js联合使用时的插件冲突(滑动冲突)
上面的截图 ,是手机端的一个滑动刷新效果.用的是scroll.js插件. 每项中又有一个滑动,是左右滑动的用swiper.js插件,查看每个班级的信息. 当手从sw ...
- 相机标定:关于用Levenberg-Marquardt算法在相机标定中应用
LM算法在相机标定的应用共有三处. (1)单目标定或双目标定中,在内参固定的情况下,计算最佳外参.OpenCV中对应的函数为findExtrinsicCameraParams2. (2)单目标定中,在 ...
- Fping
(十大特色功能) Ping是最常用的网络测试工具,ping的测试功能其实比较多,xp系统的ping有12个选项.但是,fping测试工具有25个选项,在ping的基础上增加了许多专业的功能,可用于更深 ...