JAVA concurrent包学习--Semaphore

Semaphore

简介

Semaphore是一个计数信号量,它的本质是一个"共享锁"。

信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

方法列表

// 创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits)
// 创建具有给定的许可数和给定的公平设置的 Semaphore。
Semaphore(int permits, boolean fair)

// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,或者线程被中断。
void acquire()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
void acquire(int permits)
// 从此信号量中获取许可,在有可用的许可前将其阻塞。
void acquireUninterruptibly()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
void acquireUninterruptibly(int permits)
// 返回此信号量中当前可用的许可数。
int availablePermits()
// 获取并返回立即可用的所有许可。
int drainPermits()
// 返回一个 collection,包含可能等待获取的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待获取的线程的估计数目。
int getQueueLength()
// 查询是否有线程正在等待获取。
boolean hasQueuedThreads()
// 如果此信号量的公平设置为 true,则返回 trueboolean isFair()
// 根据指定的缩减量减小可用许可的数目。
protected 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)

个人理解

Semaphore信号量 个人理解成一个许可证池(初始数量允许<0)

关键操作

当调用acquire()时  若剩余的许可证数量能满足需求是  立即返回    否则 持续等待 直到许可数量满足该线程要求的许可数量

调用drainPermits()将清空当前Semaphore的数量  将数量置为0  同时返回清空的许可证数量
调用release(permits) 将往Semaphore的许可证池增加permits数量  permits不允许为负   默认为1

调用acquire(?)acquireUninterruptibly(?)的区别是  acquire允许被线程打断而acquireUninterruptibly不允许
调用acquire(?)tryAcquire(?)的区别是tryAcquire是立即返回  返回结果是当许可证足够时返回true,否则返回false
调用tryAcquire(?)tryAcquire(?TimeUtil...)的区别是tryAcquire(?TimeUtil...)当未获取到足够的许可时会尝试等待一段时间继续尝试获取

构造方法默认创建一个非公平Semaphore  其中公平和非公平的区别在于  公平的要求等候的线程先进先出(队列模型),而非公平的只要当前剩余的许可需求能被满足,就交给获取的线程(先满足能满足的)

使用场景

刚接触Semaphore的时候,同事举了个蹲坑的栗子:

Semaphore semaphore = new Semaphore(5);
        AtomicInteger ai = new AtomicInteger();
        for (int i = 0; i < 10; i++) {
            new Thread(
                ()->{
                    try {
                        int num = ai.incrementAndGet();
                        long t1 = System.currentTimeMillis();
                        semaphore.acquire();
                        long t2 = System.currentTimeMillis();
                        System.out.println(String.format("people%s 占到坑 等待时间:%sms, 开始享受...", num,(t2-t1)));
                        Thread.sleep(500+new Random().nextInt(500));
                        long t3 = System.currentTimeMillis();
                        System.out.println(String.format("people%s 使用完毕 总共耗时:%sms, 离开...", num,  (t3-t2)));
                        semaphore.release();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                ).start();
        }
people5 占到坑 等待时间:0ms, 开始享受...
people4 占到坑 等待时间:0ms, 开始享受...
people1 占到坑 等待时间:0ms, 开始享受...
people3 占到坑 等待时间:0ms, 开始享受...
people2 占到坑 等待时间:0ms, 开始享受...
people2 使用完毕 总共耗时:539ms, 离开...
people6 占到坑 等待时间:538ms, 开始享受...
people1 使用完毕 总共耗时:598ms, 离开...
people7 占到坑 等待时间:597ms, 开始享受...
people3 使用完毕 总共耗时:697ms, 离开...
people8 占到坑 等待时间:696ms, 开始享受...
people5 使用完毕 总共耗时:714ms, 离开...
people9 占到坑 等待时间:714ms, 开始享受...
people4 使用完毕 总共耗时:997ms, 离开...
people10 占到坑 等待时间:997ms, 开始享受...
people6 使用完毕 总共耗时:563ms, 离开...
people7 使用完毕 总共耗时:751ms, 离开...
people9 使用完毕 总共耗时:716ms, 离开...
people10 使用完毕 总共耗时:554ms, 离开...
people8 使用完毕 总共耗时:885ms, 离开...

示例代码(java 1.8)

        Semaphore s = new Semaphore(10, true);//公平
        //Semaphore s = new Semaphore(10);//非公平


        List<Integer> list = Arrays.asList(3,4,7,2);
        list.forEach(i->{
            new Thread(()->{
                System.out.println(String.format("runner:%s wait for begin...", i));

                try {
                    s.acquire(i);

                    Thread.sleep(2000);
                } catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    s.release(i);
                }
                System.out.println(String.format("runner:%s wait over...", i));
            }).start();

            try {
                Thread.sleep(50);
            } catch (Exception e2) {
            }
        });

输出结果

公平semaphore输出结果

runner:3 wait for begin...
runner:4 wait for begin...
runner:7 wait for begin...
runner:2 wait for begin...
runner:3 wait over...
runner:4 wait over...
runner:7 wait over...
runner:2 wait over...

非公平semaphore输出结果

runner:3 wait for begin...
runner:4 wait for begin...
runner:7 wait for begin...
runner:2 wait for begin...
runner:3 wait over...
runner:4 wait over...
runner:2 wait over...
runner:7 wait over...

参考博文

参考博文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值