zoukankan      html  css  js  c++  java
  • 信号量Semaphore的使用

    一、概念

    Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。

    一个信号量有且仅有3种操作,且它们全部是原子的:初始化、增加和减少 
    增加可以为一个进程解除阻塞; 
    减少可以让一个进程进入阻塞。

    和线程池的区别:使用Seamphore,创建了多少线程,实际就会有多少线程进行执行,只是可同时执行的线程数量会受到限制。但使用线程池,不管你创建多少线程,实际可执行的线程数是一定的。

    二、方法

    1 构造方法:

    Semaphore(int)、Semaphore(int,boolean)

    int表示该信号量拥有的许可数量

    boolean表示获取许可的时候是否是公平的。(公平指的是先来的先执行)

    2 获取许可

    acquire()、acquire(int)、tryAcquire()

    int参数表示一次性要获取几个许可,默认为1个,acquire方法在没有许可的情况下,要获取许可的线程会阻塞。

    tryAcquire()方法在没有许可的情况下会立即返回 false,要获取许可的线程不会阻塞。

    3 释放许可

    release()、release(int)

    int参数表示一次性要释放几个许可,默认为1个,

    注意一个线程调用release()之前并不要求一定要调用了acquire因此如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了(实现动态增加)

    4 当前可用的许可数

    int availablePermits()

    三、测试

    public void testSemaphore()
    {
        // 线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        // 只能5个线程同时访问
        final Semaphore semp = new Semaphore(2);
        // 模拟20个客户端访问
        for (int index = 0; index < 5; index++) {
            final int NO = index;
            Runnable run = new Runnable() {
                @Override
                public void run() {
                    try {
                        if (semp.availablePermits() > 0) {
                            System.out.println( NO + "线程启动");
                        else {
                            System.out.println(NO + "线程启动,排队等待");
                        }
                        // 获取许可
                        semp.acquire();
                        System.out.println(NO + "线程执行" );
                        //模拟实际业务逻辑
                        Thread.sleep((long) (Math.random() * 10000));
                        // 访问完后,释放
                        semp.release();
                        System.out.println(NO + "线程释放");
                    catch (InterruptedException e) {
                    }
                }
            };
            exec.execute(run);
        }
     
        try {
            Thread.sleep(10);
        catch (InterruptedException e) {
            e.printStackTrace();
        }
     
        //System.out.println(semp.getQueueLength());
     
     
     
        // 退出线程池
        exec.shutdown();
    }

    0线程启动
    0线程执行
    1线程启动
    1线程执行
    2线程启动,排队等待
    3线程启动,排队等待
    4线程启动,排队等待
    2线程执行
    0线程释放
    1线程释放
    3线程执行
    2线程释放
    4线程执行
    3线程释放
    4线程释放

     
  • 相关阅读:
    Reversing Encryption(模拟水题)
    Alphabetic Removals(模拟水题)
    Mishka and Contest(模拟水题)
    DFS中的奇偶剪枝(技巧)
    三分法搜索
    最短的包含字符串 (尺取)
    Android开发:最详细的 NavigationDrawer 开发实践总结
    Android开发:最详细的 Toolbar 开发实践总结
    Android开发:Translucent System Bar 的最佳实践
    Android微信智能心跳方案
  • 原文地址:https://www.cnblogs.com/aiguona/p/10634045.html
Copyright © 2011-2022 走看看