java 中的 Semaphore 信号量学习小记

Semaphore 学习小记

Semaphore是JDK提供的一个同步工具,它通过维护若干个许可证来控制线程对共享资源的访问。

信号量的作用是维护一个 “许可证” 的计数,线程可以获取 “许可证”,那信号量剩余的 “许可证” 减一,线程可以释放一个许可证,那 “许可证” 的数量就加一, 当信号量所拥有的许可证是0 时候,那么下一个获取许可证的线程就需要等待,只能有另外的线程释放了许可证。

Semaphore 信号量的使用流程

1.初始化Semaphore并许可证的数量
  • Semaphore(int permits); // 生成指定数量许可证, 排队策略为非公平
  • Semaphore(int permits, boolean fair) // 生成指定数量的许可证,并设置排队策略是否为公平的
2.在需要被许可的地方加 acquire() 相关的方法获取许可证
  • acquire() // 获取许可证并可以相应中断
  • acquireUninterruptibly() // 获取许可证并不可以相应中断
  • tryAcquire() // 如果当前有空闲的许可证直接获取,如果没有如果没有我不必阻塞,我可以先做别的事情
  • tryAcquire(long timeout, TimeUnit unit) // 和tryAcquire()一样,但多了一个超时间的时间,如在三秒内获取不到,我就做别的事情
3.在任务执行结束的时候调用 release() 方法释放许可证

Semaphore 使用


public class SemaphoreDemo {
    // 生成三个许可证
    static Semaphore semaphore = new Semaphore(3);

    public static void main(String[] args) {
        // 定义一个固定数量为 30 个的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(30);
        for (int i = 1; i <= 30; i++) {
            // 生成 30 个任务提交给线程池
            executorService.submit(new Task());
        }
        executorService.shutdown();
    }

    static class Task implements Runnable {
        @Override
        public void run() {
            try {
                // 获取许可证
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 拿到许可证... ");
            try {
                // 暂定任务耗时 2s
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 释放许可证... ");
            // 释放许可证
            semaphore.release();
        }
    }
}

运行结果
在这里插入图片描述

Semaphore 信号量的特殊使用

一次性获取或释放多个许可证。比如TaskA会调用很消耗资源的method1(),而TaskB调用的是不太消耗资源的method2(),假设我们一共有5个许可证。那么我们就可以要求TaskA获取5个许可证才能执行而TaskB只需要获取到一个许可证就能执行,这样就避免了A和B同时运行的情况,我们可以根据自己的需求合理分配资源。

Semaphore 信号量使用注意点

  1. 获取和释放的许可证数量必须一致,否则比如每次都获取2个但是只释放1个甚至不释放,随着时间的推移,到最后许可证数量不够用,会导致程序卡死。(虽然信号量类并不对是否和获取的数量做规定,但是这是我们的编程规范,否则容易出错)
  2. 在初始化Semaphore 时候公平性设置为 ture 比较合理,要不然会出现线程饥饿的情况
  3. 并不是必须由获取许可证的线程释放那个许可证,事实上,获取和释放许可证对线程并无要求,也许是A获取了,然后由B释放,只要逻辑合理即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值