Semaphore 信号量

来源:互联网 发布:淘宝买水果靠谱吗 知乎 编辑:程序博客网 时间:2024/04/30 04:21

java.util.concurrent.Semaphore.Semaphore(int permits)

构造函数,指定许可证的数量。代表共享资源的个数。可以设为0.也可以设为负数。

void java.util.concurrent.Semaphore.acquire() throws InterruptedException

从信号量中获得一个许可证。若得不到会被阻塞,直到有一个许可证可用。


void java.util.concurrent.Semaphore.release()

释放一个许可证,还给信号量。


笔记摘要:

               这里主要介绍了java5中线程锁技术以外的其他同步工具,首先介绍semaphore:一个计数信号量。用于控制同时访问资源的线程个数,

               CyclicBarrier同步辅助类:从字面意思看是路障,这里用于线程之间的相互等待,到达某点后,继续向下执行,CountDownLatch同步辅

              助类:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。犹如倒计时计数器,然后是Exchangeer:实现两个

             对象之间数据交换,可阻塞队列:ArrayBlockingQueue,通过阻塞队列间的通信来演示其作用,最后介绍了几个同步集合。



一、Semaphore实现信号灯


        1.、Semaphore可以维护当前访问自身的线程个数,并提供了同步机制,使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许

       的并发访问数。Semaphore 只对可用许可的号码进行计数,并采取相应的行动。 

   

        2、Semaphore实现的功能就像:银行办理业务,一共有5个窗口,但一共有10个客户,一次性最多有5个客户可以进行办理,其他的人必须等候,

     当5客户中的任何一个离开后,在等待的客户中有一个人可以进行业务办理。


        3、Semaphore提供了两种规则:

               一种是公平的:获得资源的先后,按照排队的先后。在构造函数中设置true实现

               一种是野蛮的:谁有本事抢到资源,谁就可以获得资源的使用权。


       4、与传统的互斥锁的异同:

             单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁“,再由另外一个线程释放”锁“,

       这可以应用于死锁恢复的一些场合。


      5、应用场景:共享资源的争夺,例如游戏中选手进入房间的情况。


  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. import java.util.concurrent.Semaphore;  
  4.   
  5. public class SemaphoreTest {  
  6.     public static void main(String[] args) {  
  7.           
  8.   //创建一个可根据需要创建新线程的线程池  
  9.   ExecutorService service = Executors.newCachedThreadPool();  
  10.         final  Semaphore sp = new Semaphore(3);  
  11.           
  12.   //创建10个线程  
  13.   for(int i=0;i<10;i++){  
  14.             Runnable runnable = new Runnable(){  
  15.                     public void run(){  
  16.                     try {  
  17.                         sp.acquire();   //获取灯,即许可权  
  18.                     } catch (InterruptedException e1) {  
  19.                         e1.printStackTrace();  
  20.                     }  
  21.                     System.out.println("线程" + Thread.currentThread().getName() +   
  22.                             "进入,当前已有" + (3-sp.availablePermits()) + "个并发");  
  23.                     try {  
  24.                         Thread.sleep((long)(Math.random()*10000));  
  25.                     } catch (InterruptedException e) {  
  26.                         e.printStackTrace();  
  27.                     }  
  28.                     System.out.println("线程" + Thread.currentThread().getName() +   
  29.                             "即将离开");                      
  30.                     sp.release();   // 释放一个许可,将其返回给信号量  
  31.   
  32.                     //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元  
  33.                     System.out.println("线程" + Thread.currentThread().getName() +   
  34.                             "已离开,当前已有" + (3-sp.availablePermits()) + "个并发");                      
  35.                 }  
  36.             };  
  37.             service.execute(runnable);            
  38.         }  
  39.     }  
  40.   
  41. }  

0 0
原创粉丝点击