AQS之Semaphore

版权声明:我挥舞着键盘和本子, 发誓要把世界写个明明白白。 https://blog.csdn.net/qq_28938627/article/details/80780228

AQS在功能上有独占控制和共享控制

Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源

Semaphore 同一时间最多允许5个线程同时执行acquire方法和release方法之间的代码

Semaphore semaphore = new Semaphore(5);


@Slf4j
public class SemaphoreExample1 {

    private final static int threadCount = 20;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final Semaphore semaphore = new Semaphore(5);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;

            exec.execute(() -> {
                try {
                    semaphore.acquire(); // 获取一个许可
                    test(threadNum);
                    semaphore.release(); // 释放一个许可
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        log.info("{}", threadNum);
        Thread.sleep(1000);
    }
}
00:28:59.911 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 1
00:28:59.916 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 0
00:28:59.916 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 2
00:28:59.916 [pool-1-thread-4] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 3
00:28:59.916 [pool-1-thread-5] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 4
00:29:00.922 [pool-1-thread-6] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 5
00:29:00.922 [pool-1-thread-7] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 6
00:29:00.922 [pool-1-thread-8] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 7
00:29:00.925 [pool-1-thread-9] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 8
00:29:00.937 [pool-1-thread-10] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 9
00:29:01.922 [pool-1-thread-12] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 11
00:29:01.922 [pool-1-thread-11] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 10
00:29:01.922 [pool-1-thread-13] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 12
00:29:01.925 [pool-1-thread-14] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 13
00:29:01.937 [pool-1-thread-15] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 14
00:29:02.923 [pool-1-thread-16] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 15
00:29:02.923 [pool-1-thread-17] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 16
00:29:02.923 [pool-1-thread-18] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 17
00:29:02.926 [pool-1-thread-19] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 18
00:29:02.938 [pool-1-thread-20] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 19

由运行结果可以看出
在同一时刻有5个线程执行acquire方法和release方法之间的代码,之后休眠一秒再次执行

表示允许的最高并发线程数量为5

我们还可以设置acquire()一次获取的许可的数量,
例如将信号量设置为10 一个获取许可为3,则一次有10/3=3个线程同时执行

只有许可不为0时,线程才能执行方法,否则会一直阻塞




@Slf4j
public class SemaphoreExample1 {

    private final static int threadCount = 60;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final Semaphore semaphore = new Semaphore(10);




        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;

            exec.execute(() -> {
                try {
                    System.out.println("开始----------------------------" +Thread.currentThread()+ semaphore.availablePermits());
                    semaphore.acquire(3); // 获取一个许可
                    System.out.println("进入之后------------------------ " +Thread.currentThread()+ semaphore.availablePermits());
                    test(threadNum);
                    semaphore.release(3); // 释放一个许可
                    System.out.println("释放之后----------------------------" +Thread.currentThread()+ semaphore.availablePermits());
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        log.info("{}", threadNum);
        Thread.sleep(100);

    }
}

可以使用

if (semaphore.tryAcquire()) { // 尝试获取一个许可
                        test(threadNum);
                        semaphore.release(); // 释放一个许可
                    }

如果无法获取许可就结束了

tryAcquire还有另外一个重载
在获取许可时进行等待多少秒,如果N秒之后仍无法获取许可则结束

    public boolean tryAcquire(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

猜你喜欢

转载自blog.csdn.net/qq_28938627/article/details/80780228