zoukankan      html  css  js  c++  java
  • 并发库应用之七 & 信号灯Semaphore应用

      Semaphore可以维护当前访问自身的线程个数,并且提供了同步机制。

      Semaphore实现的功能类似于厕所里有5个坑,有10个人要上厕所,同时就只能有5个人占用,当5个人中 的任何一个让开后,其中在等待的另外5个人中又有一个可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项(常见于 限流 机制场景应用中):

      Semaphore(int permits)

      Semaphore(int permits, boolean fair)

      JDK包位置:java.util.concurrent.Semaphore

      一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。

      Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。例如,下面的类使用信号量控制对内容池的访问:

     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         ExecutorService service = Executors.newCachedThreadPool();
     9         //可容纳的线程并发数
    10         final Semaphore sp = new Semaphore(3);
    11         for (int i = 0; i < 10; i++) {
    12             Runnable runnable = new Runnable() {
    13                 public void run() {
    14                     try {
    15                         //从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断
    16                         sp.acquire();
    17                     } catch (InterruptedException e1) {
    18                         e1.printStackTrace();
    19                     }
    20                     System.out.println(String.format("线程%s进入,当前已有%d个并发", Thread.currentThread().getName(), (3 - sp.availablePermits())));
    21                     try {
    22                         Thread.sleep((long) (Math.random() * 10000));
    23                     } catch (InterruptedException e) {
    24                         e.printStackTrace();
    25                     }
    26                     System.out.println(String.format("线程【%s】已经离开-------BYE BYE", Thread.currentThread().getName()));
    27                     sp.release();//释放一个许可,将其返回给信号量
    28                 }
    29             };
    30             service.execute(runnable);//提交了10个任务放入到线程队列
    31         }
    32         try {
    33             while (true) {
    34                 if (sp.availablePermits() == 3) {
    35                     System.out.println("****************所有线程执行完毕****************");
    36                     break;
    37                 }
    38             }
    39         } finally {
    40             service.shutdown();
    41         }
    42     }
    43 }

    上述代码运行结果如下所示:

      

      总结:传统互斥只能内部释放锁this.unlock(),进去this.lock()晕倒了别人就没法进去了;单个信号量的Semaphore对象也可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,sp.release()  sp.acquire()。这可应用于死锁恢复的一些场合

    提示:欢迎继续参看我相关的下一篇博客:并发库应用之八 & 循环路障CyclicBarrier应用

  • 相关阅读:
    初级算法-1.从排序数组中删除重复项
    一个字符串匹配函数...
    Working With JSON
    javascript iterator
    js 正则表达式验证密码、邮箱格式.....
    SpringMVC 定时任务
    JS 数组去重
    JAVA 跨域请求 不用JSONP 不用CORS
    openLayer 跳到指定坐标
    清空CheckBox 勾选
  • 原文地址:https://www.cnblogs.com/liang1101/p/6526039.html
Copyright © 2011-2022 走看看