信号量Semaphore的使用

时间:2021-07-12 05:23:32

一、概念

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

一个信号量有且仅有3种操作,且它们全部是原子的:初始化、增加和减少 
增加可以为一个进程解除阻塞; 
减少可以让一个进程进入阻塞。

和线程池的区别:使用Seamphore,创建了多少线程,实际就会有多少线程进行执行,只是可同时执行的线程数量会受到限制。但使用线程池,不管你创建多少线程,实际可执行的线程数是一定的。

二、方法

1 构造方法:

Semaphore(int)、Semaphore(int,boolean)

int表示该信号量拥有的许可数量

boolean表示获取许可的时候是否是公平的。(公平指的是先来的先执行)

2 获取许可

acquire()、acquire(int)、tryAcquire()

int参数表示一次性要获取几个许可,默认为1个,acquire方法在没有许可的情况下,要获取许可的线程会阻塞。

tryAcquire()方法在没有许可的情况下会立即返回 false,要获取许可的线程不会阻塞。

3 释放许可

release()、release(int)

int参数表示一次性要释放几个许可,默认为1个,

注意一个线程调用release()之前并不要求一定要调用了acquire因此如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了(实现动态增加)

4 当前可用的许可数

int availablePermits()

三、测试

public  void  testSemaphore()
{
     // 线程池
     ExecutorService exec = Executors.newCachedThreadPool();
     // 只能5个线程同时访问
     final  Semaphore semp =  new  Semaphore( 2 );
     // 模拟20个客户端访问
     for  ( int  index =  0 ; index <  5 ; index++) {
         final  int  NO = index;
         Runnable run =  new  Runnable() {
             @Override
             public  void  run() {
                 try  {
                     if  (semp.availablePermits() >  0 ) {
                         System.out.println( NO +  "线程启动" );
                     else  {
                         System.out.println(NO +  "线程启动,排队等待" );
                     }
                     // 获取许可
                     semp.acquire();
                     System.out.println(NO +  "线程执行"  );
                     //模拟实际业务逻辑
                     Thread.sleep(( long ) (Math.random() *  10000 ));
                     // 访问完后,释放
                     semp.release();
                     System.out.println(NO +  "线程释放" );
                 catch  (InterruptedException e) {
                 }
             }
         };
         exec.execute(run);
     }
 
     try  {
         Thread.sleep( 10 );
     catch  (InterruptedException e) {
         e.printStackTrace();
     }
 
     //System.out.println(semp.getQueueLength());
 
 
 
     // 退出线程池
     exec.shutdown();
}

 

0线程启动
0线程执行
1线程启动
1线程执行
2线程启动,排队等待
3线程启动,排队等待
4线程启动,排队等待
2线程执行
0线程释放
1线程释放
3线程执行
2线程释放
4线程执行
3线程释放
4线程释放