并发工具类系列:java
Java并发工具类(闭锁CountDownLatch)数据库
Java并发工具类(栅栏CyclicBarrier)bash
计数信号量用来控制同时访问某个特定资源的操做数量,或者同时执行某个指定操做的数量。信号量还能够用来实现某种资源池,或者对容器施加边界。dom
Semaphore管理着一组许可(permit),许可的初始数量能够经过构造函数设定,操做时首先要获取到许可,才能进行操做,操做完成后须要释放许可。若是没有获取许可,则阻塞到有许可被释放。若是初始化了一个许可为1
的Semaphore,那么就至关于一个不可重入的互斥锁(Mutex)。函数
理论的听起来有些绕口,其实假设生活中一个常见的场景:天天早上,你们都热衷于带薪上厕所,可是公司厕所一共只有10
个坑位。。那么只能同时10
我的用着,后面来的人都得等着(阻塞),若是走了2
我的,那么又能够进去2
我的。这里面就是Semaphore的应用场景,争夺有限的资源。工具
package concurrency;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
class Employee implements Runnable {
private String id;
private Semaphore semaphore;
private static Random rand= new Random(47);
public Employee(String id, Semaphore semaphore) {
this.id = id;
this.semaphore = semaphore;
}
public void run() {
try {
semaphore.acquire();
System.out.println(this.id + "is using the toilet");
TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000));
semaphore.release();
System.out.println(this.id + "is leaving");
} catch (InterruptedException e) {
}
}
}
public class ToiletRace {
private static final int THREAD_COUNT = 30;
private static ExecutorService threadPool = Executors
.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(10);
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
threadPool.execute(new Employee(String.valueOf(i), s));
}
threadPool.shutdown();
}
}
复制代码
这里我定义了30我的要上厕所,可是只有10个坑位,每一个人消耗随机的时间,直接运行上面这段代码,能够看到一开始进去了10我的,后来就是陆陆续续的有人进,有人出了。可是正在使用的必定不会超过10个的。post
Semaphore是很好用的Java并发工具,除了上面这个例子,咱们在工做中常常用它管理数据库链接或者保护其它受限资源的并发使用。固然Semaphore还有其它的一些方法,能够查看剩余的许可数,能够查看正在使用许可的线程数,具体使用时能够查看官方文档。ui