Java并发编程札记-(四)JUC锁-10Semaphore简介

一般的锁在任意时刻只允许一个线程访问一项资源,而计数信号量允许n个任务同时访问一项资源。我们可以将信号量看做一个许可集,可以向线程分发使用资源的许可证。获得资源前,线程调用acquire()从许可集中获取许可。该线程结束后,通过release()将许可还给许可集。

函数列表

//构造方法摘要
Semaphore(int permits) 
          //创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits, boolean fair) 
          //创建具有给定的许可数和给定的公平设置的 Semaphore。 
//方法摘要
 void   acquire() 
          //从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
 void   acquire(int permits) 
          //从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
 void   acquireUninterruptibly() 
          //从此信号量中获取许可,在有可用的许可前将其阻塞。
 void   acquireUninterruptibly(int permits) 
          //从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
 int    availablePermits() 
          //返回此信号量中当前可用的许可数。
 int    drainPermits() 
          //获取并返回立即可用的所有许可。
protected  Collection<Thread>   getQueuedThreads() 
          //返回一个 collection,包含可能等待获取的线程。
 int    getQueueLength() 
          //返回正在等待获取的线程的估计数目。
 boolean    hasQueuedThreads() 
          //查询是否有线程正在等待获取。
 boolean    isFair() 
          //如果此信号量的公平设置为 true,则返回 trueprotected  void reducePermits(int reduction) 
          //根据指定的缩减量减小可用许可的数目。
 void   release() 
          //释放一个许可,将其返回给信号量。
 void   release(int permits) 
          //释放给定数目的许可,将其返回到信号量。
 String toString() 
          //返回标识此信号量的字符串,以及信号量的状态。
 boolean    tryAcquire() 
          //仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
 boolean    tryAcquire(int permits) 
          //仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。
 boolean    tryAcquire(int permits, long timeout, TimeUnit unit) 
          //如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
 boolean    tryAcquire(long timeout, TimeUnit unit) 
          //如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。  

此类的构造方法可选地接受一个公平参数fair。当fair设置为false时,此类不对线程获取许可的顺序做任何保证,也就是说可以在已经等待的线程前为调用acquire() 的线程分配一个许可。当公平设置为true时,信号量保证对于任何调用acquire()的线程而言,都按照FIFO的规则来选择线程、获得许可。注意,FIFO排序必然应用到这些方法内的指定内部执行点。所以,可能某个线程先于另一个线程调用了 acquire(),但是却在该线程之后到达排序点,并且从方法返回时也类似。还要注意,非同步的tryAcquire()方法不使用公平设置,而是使用任意可用的许可。

通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。

例1:信号量的简单使用

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        // 创建许可数为3和非公平的公平设置的 Semaphore。
        final Semaphore semp = new Semaphore(3);
        // 模拟10个客户端访问
        for (int index = 0; index < 10; index++) {
            Runnable run = new Runnable() {
                public void run() {
                    try {
                        // 从此信号量获取一个许可
                        semp.acquire();
                        System.out.println(Thread.currentThread().getName());
                    } catch (InterruptedException e) {
                    } finally {
                        // 释放信号量。如果没有这条语句,则在控制台只能打印5条记录,之后线程一直阻塞
                        semp.release();
                    }
                }
            };
            exec.execute(run);
        }
        exec.shutdown();
    }
}

源码
待补充

本文就讲到这里,想了解Java并发编程更多内容请参考:

  • Java并发编程札记-目录
    原文作者:java并发
    原文地址: http://blog.csdn.net/panweiwei1994/article/details/78827248
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞