并发编程系列之Semaphore用法简介

2021-11-30 19:18:28 浏览数 (1)

1、Semaphore计数信号量定义

理解:就是要给令牌池,可获取信号量(令牌或者许可)、放入信号量。常用于控制并发的线程数,也可用于池类资源的访问控制。

2、Semaphore用法api

  • 构造方法
    • Semaphore(int permits):指定初始许可数
    • Semaphore(int permits , boolean fair):指定是否公平模式
  • 尝试获取许可
    • boolean tryAcquire(long timeout , TimeUnit unit)
    • boolean tryAcquire(int permits)
    • boolean tryAcquire(int permits, long timeout , TimeUnit unit)
  • 获取许可
    • void acquire() throws InterruptedException;:获取1个许可,可中断
    • void acquire(int permits) throws InterruptedException;:获取指定数量的许可,可中断
    • void acquireUninterruptibly():获取1个许可,不可中断
    • void acquireUninterruptibly(int permits)
    • int drainPermits():获取当前所有可用的
  • 放入许可
    • void release():放入1个
    • void release(int permits):放入多个
  • 其它API
    • boolean isFair()
    • int availablePermits
    • boolean hasQueuedThreads()
    • int getQueueLength()
    • Collection<Thread> getQueuedThreads()

3、Semaphore例子

场景:一个共享汽车场地有10辆汽车,但是有20个人需要借车,一辆汽车只能被一个人租赁,只有使用还车之后,其他人才能继续使用租赁

代码语言:javascript复制
import java.util.Random;
import java.util.concurrent.Semaphore;

/**
 * <pre>
 *      Semaphore example
 * </pre>
 *
 * <pre>
 * @author mazq
 * 修改记录
 *    修改后版本:     修改人:  修改日期: 2021/11/30 14:16  修改内容:
 * </pre>
 */
public class SemaphoreExample {
    // 公平模式
    private Semaphore semaphore = new Semaphore(10, true);
    private final Random random = new Random();

    public void userCar() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()   "需要用车");
        long start = System.currentTimeMillis();
        // 获取许可
        semaphore.acquire();
        System.out.println(Thread.currentThread().getName()   "租车成功,等待了:"  (System.currentTimeMillis() - start));
        try {
            Thread.sleep(random.nextInt(10_000));
        }catch (InterruptedException e) {
        } finally {
            System.out.println(Thread.currentThread().getName()   "还车了!");
            // 释放许可
            semaphore.release();
        }
    }

    public static void main(String[] args) {
        final Random ran = new Random();
        final SemaphoreExample semaphoreExample = new SemaphoreExample();
        for (int i = 0; i < 20 ; i  ) {
            new Thread(()-> {
                try {
                    Thread.sleep(ran.nextInt(5_000));
                    semaphoreExample.userCar();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
代码语言:javascript复制
Thread-8需要用车
Thread-8租车成功,等待了:0
Thread-1需要用车
Thread-1租车成功,等待了:0
Thread-12需要用车
Thread-12租车成功,等待了:0
Thread-6需要用车
Thread-6租车成功,等待了:0
Thread-13需要用车
Thread-13租车成功,等待了:0
Thread-15需要用车
Thread-15租车成功,等待了:0
Thread-19需要用车
Thread-19租车成功,等待了:0
Thread-5需要用车
Thread-5租车成功,等待了:0
Thread-18需要用车
Thread-18租车成功,等待了:0
Thread-0需要用车
Thread-0租车成功,等待了:0
Thread-7需要用车
Thread-11需要用车
Thread-10需要用车
Thread-13还车了!
Thread-7租车成功,等待了:461
Thread-14需要用车
Thread-2需要用车
Thread-3需要用车
Thread-4需要用车
Thread-15还车了!
Thread-11租车成功,等待了:1291
Thread-0还车了!
Thread-10租车成功,等待了:1601
Thread-9需要用车
Thread-10还车了!
Thread-14租车成功,等待了:2008
Thread-17需要用车
Thread-16需要用车
Thread-11还车了!
Thread-2租车成功,等待了:2858
Thread-6还车了!
Thread-3租车成功,等待了:2513
Thread-8还车了!
Thread-4租车成功,等待了:3218
Thread-7还车了!
Thread-9租车成功,等待了:2420
Thread-12还车了!
Thread-17租车成功,等待了:3266
Thread-3还车了!
Thread-16租车成功,等待了:3329
Thread-19还车了!
Thread-1还车了!
Thread-17还车了!
Thread-5还车了!
Thread-4还车了!
Thread-18还车了!
Thread-2还车了!
Thread-14还车了!
Thread-9还车了!
Thread-16还车了!

0 人点赞