zoukankan      html  css  js  c++  java
  • java并发之Semaphore

    一、定义

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

      Semaphore通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。

    二、使用场景代码示例

      比方说我们有个资源访问连接池,每次只能同时允许2个线程访问资源,当某个线程或许到资格访问资源业务完成线程结束,它还要自动释放,让其它线程可以访问。

     1 public class Test {
     2 
     3     public static void main(String[] args) throws IOException {
     4         ExecutorService executorService = Executors.newCachedThreadPool();
     5         // 配置同时只能有两个线程访问
     6         Semaphore semaphore = new Semaphore(2);
     7         // 开启10个线程
     8         for (int i = 0; i < 10; i++) {
     9             executorService.execute(new TaskRunn(semaphore));
    10         }
    11         // 关闭线程池
    12         executorService.shutdown();
    13         while (true) {
    14             System.out.println(Thread.currentThread().getName()+"semaphore这个信号量中当前可用的许可数:"+semaphore.availablePermits());
    15             System.out.println(Thread.currentThread().getName()+"正在等待获取的线程的估计数目:"+semaphore.getQueueLength());
    16 //            System.out.println(Thread.currentThread().getName()+"查询是否有线程正在等待获取:"+semaphore.hasQueuedThreads());
    17             if (semaphore.getQueueLength() == 0) {
    18                 break;
    19             }
    20             try {
    21                 Thread.sleep(1000);
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25         }
    26     }
    27 }
    28 
    29 class TaskRunn implements Runnable{
    30 
    31     private Semaphore semaphore;
    32     public TaskRunn(Semaphore semaphore) {
    33         this.semaphore = semaphore;
    34     }
    35     
    36     @Override
    37     public void run() {
    38         try {
    39             System.out.println(Thread.currentThread().getName()+"begin...");
    40             semaphore.acquire();// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断
    41             Thread.sleep(5000);// 模拟业务耗时
    42             semaphore.release();// 释放一个许可,将其返回给信号量
    43             System.out.println(Thread.currentThread().getName()+"end...");
    44         } catch (InterruptedException e) {
    45             e.printStackTrace();
    46         }
    47     }
    48     
    49 }

    打印信息

    mainsemaphore这个信号量中当前可用的许可数:2
    main正在等待获取的线程的估计数目:0
    pool-1-thread-1begin...
    pool-1-thread-2begin...
    pool-1-thread-3begin...
    pool-1-thread-4begin...
    pool-1-thread-5begin...
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:3
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:3
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:3
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:3
    pool-1-thread-1end...
    pool-1-thread-2end...
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:1
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:1
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:1
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:1
    mainsemaphore这个信号量中当前可用的许可数:0
    main正在等待获取的线程的估计数目:1
    pool-1-thread-3end...
    pool-1-thread-4end...
    mainsemaphore这个信号量中当前可用的许可数:1
    main正在等待获取的线程的估计数目:0
    mainsemaphore这个信号量中当前可用的许可数:1
    main正在等待获取的线程的估计数目:0
    mainsemaphore这个信号量中当前可用的许可数:1
    main正在等待获取的线程的估计数目:0
    mainsemaphore这个信号量中当前可用的许可数:1
    main正在等待获取的线程的估计数目:0
    mainsemaphore这个信号量中当前可用的许可数:1
    main正在等待获取的线程的估计数目:0
    pool-1-thread-5end...
    mainsemaphore这个信号量中当前可用的许可数:2
    main正在等待获取的线程的估计数目:0
  • 相关阅读:
    Codeforces Round #702 (Div. 3) 题解
    Educational Codeforces Round 104 (Rated for Div. 2) A~E题解
    AtCoder Regular Contest 112 A~D题解
    Codeforces Round #701 (Div. 2) A~E 题解
    java String, StringBuffer, StringBuilder简单介绍和使用
    货仓选址
    线程的同步
    数据结构课设作业
    线程的生命周期(java 图)
    JAVA多线程的创建和使用
  • 原文地址:https://www.cnblogs.com/shamo89/p/6710103.html
Copyright © 2011-2022 走看看