Java 多线程 - 13 - Java 并发工具类 Semaphore

概述

Semaphore 也叫信号量,在 JDK1.5 被引入,可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。

Semaphore 内部维护了一个计数器,其值为可以访问的共享资源的个数.一个线程要访问共享资源,先获得信号量,如果信号量的计数器值大于 1 ,意味着有共享资源可以访问,则使其计数器值减去 1 ,再访问共享资源.

如果计数器值为 0 ,线程进入休眠.当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加 1 ,之前进入休眠的线程将被唤醒并再次试图获得信号量.

访问特定资源前,必须使用 acquire 方法获得许可,如果许可数量为 0 ,该线程则一直阻塞,直到有可用许可.

访问资源后,使用 release 释放许可.

Semaphore 和 ReentrantLock 类似,获取许可有公平策略和非公平许可策略,默认情况下使用非公平策略.

API

// 构造方法
// permits 初始数量
public Semaphore(int permits)
# fair 是否使用公平策略,true: 公平策略,采用先来先用的算法,false: 非公平策略,完全随机,默认使用非公平策略.
public Semaphore(int permits, boolean fair)

// acquire 函数
// 申请一个资源
public void acquire() throws InterruptedException 
// 申请 permits 个资源
public void acquire(int permits) throws InterruptedException

// acquireUninterruptibly 函数
// 线程在申请资源过程中被打断,依然会继续申请,只不过获取资源的时间可能会有所变化.
public void acquireUninterruptibly()
public void acquireUninterruptibly(int permits)

// tryAcquire 函数
// 申请一个资源,如果当前有可用资源,立即返回 true ,否则立即返回 false
public boolean tryAcquire()
// 申请一个资源,指定一个超时时间,如果当前可以资源数量足够,立即返回 true ,否则最多等待给定的时间,如果时间到还是未能获取资源,则返回 false ;如果等待过程中线程被打断,抛出 InterruptedException 异常
public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
// 和 tryAcquire() 一样,只是申请 permits 个资源
public boolean tryAcquire(int permits)
// 和 tryAcquire(long timeout, TimeUnit unit) 一样,只是申请 permits 个资源
public boolean tryAcquire(int permits, long timeout,TimeUnit unit) throws InterruptedException

// release 函数
// 释放一个资源
public void release()
// 释放 permits 个资源
public void release(int permits)

// availablePermits 函数
// 获取当前可用的资源数量
public int availablePermits()

// drainPermits 函数
// 申请当前所有可用的资源
public int drainPermits()

// reducePermits 函数
// 禁止某些资源不可用, reduction 表示禁止的数量
protected void reducePermits(int reduction)

// isFair 函数
// 判断当前的信号量是采用什么类型的策略
// true 表示采用的是公平策略,返回 false 表示采用非公平策略
public boolean isFair()

// hasQueuedThreads 函数
// 判断是否有现成正在等待申请资源, true: 有现成正在等待申请资源 false: 没有
public final boolean hasQueuedThreads()

// getQueueLength 函数
// 返回正在等待申请资源的线程的数量
public final int getQueueLength()


// getQueuedThreads 函数
// 返回当前正在等待申请资源的线程集合
protected Collection<Thread> getQueuedThreads()

使用

ExecutorService executorService = Executors.newCachedThreadPool();
// 资源最多可被10个线程并发访问
Semaphore semaphore = new Semaphore(10);
for (int i = 0; i < 20; i++) {
    final int threadnum = i;
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            try {
                System.out.println("current thread" + Thread.currentThread().getName());
                // 获取许可
                semaphore.acquire(1);
                // 释放许可
                semaphore.release(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}
// 如果不 shutdown 工程不会结束
executorService.shutdown();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老高的IT职业路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值