Semaphore是一个计数的信号量,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如实现一个文件允许的线程访问数。打个通俗的比喻,Semaphore实现的功能类似厕所有4个坑,假如有10个人上厕所,那么同时有多少个人去上厕所呢?同时只能有4个人能够占用,当4个人中的任何一个人让开后,其中在等待的另外6个人又有一个可以占用了。
1 package ch03;
2
3 import java.util.concurrent.ExecutorService;
4 import java.util.concurrent.Executors;
5 import java.util.concurrent.Semaphore;
6
7 public class SemaphoreTest {
8
9 public static void main(String[] args) {
10 ExecutorService threadPool = Executors.newCachedThreadPool();
11 //获取三个许可的信号灯
12 final Semaphore sp = new Semaphore(5);
13 for(int i=1; i<=10; i++){
14 final int index = i;
15 Runnable runable = new Runnable() {
16
17 @Override
18 public void run() {
19 try {
20 //获取一个信号灯
21 sp.acquire();
22 } catch (InterruptedException e) {
23 e.printStackTrace();
24 }
25 System.out.println("有一个"+Thread.currentThread().getName()+
26 "线程进来了,当前有"+(5-sp.availablePermits())+"线程正在并发...");
27
28 try {
29 Thread.sleep(index * 1000);
30 } catch (InterruptedException e) {
31 e.printStackTrace();
32 }
33 //释放信号灯
34 sp.release();
35 System.out.println("线程"+Thread.currentThread().getName()+"离开了,现在还有"+(5-sp.availablePermits())+"个线程!");
36 }
37 };
38 threadPool.execute(runable);
39 }
40 threadPool.shutdown();
41 }
42
43 }
至于,在等待的6个人中谁先进去,有两种方式:一种是看谁快,第二种是按排序,先来的先进去。可以通过Semaphore的构造函数指定:
如果使用排序的方式,可以将fair设为true.
除此之外,单个信号量的Semaphore对象还可以实现互斥锁的功能,只有一个灯,A线程获得,B线程就等着。传统的互斥锁,同一个线程的锁只能由自己释放,但Semaphore对象的互斥锁可以是由一个线程获得锁,再由另外一个线程释放锁,可以应用于死锁恢复的场合。比如一个人进厕所后,晕在里面了,这样的话可以去找管理员拿备用钥匙,打开门将人挪出来,这样就避免后面的人一直堵在这里。
线程:Semaphore实现信号灯,码迷,mamicode.com
时间: 2024-08-15 15:33:44