使用Semaphore


前面我们讲了各种锁的实现,本质上锁的目的是保护一种受限资源,保证同一时刻只有一个线程能访问(ReentrantLock),或者只有一个线程能写入(ReadWriteLock)。

还有一种受限资源,它需要保证同一时刻最多有N个线程能访问,比如同一时刻最多创建100个数据库连接,最多允许10个用户下载等。

这种限制数量的锁,如果用Lock数组来实现,就太麻烦了。

这种情况就可以使用Semaphore,例如,最多允许3个线程同时访问:

  1. public class AccessLimitControl {
  2. // 任意时刻仅允许最多3个线程获取许可:
  3. final Semaphore semaphore = new Semaphore(3);
  4. public String access() throws Exception {
  5. // 如果超过了许可数量,其他线程将在此等待:
  6. semaphore.acquire();
  7. try {
  8. // TODO:
  9. return UUID.randomUUID().toString();
  10. } finally {
  11. semaphore.release();
  12. }
  13. }
  14. }

使用Semaphore先调用acquire()获取,然后通过try ... finally保证在finally中释放。

调用acquire()可能会进入等待,直到满足条件为止。也可以使用tryAcquire()指定等待时间:

  1. if (semaphore.tryAcquire(3, TimeUnit.SECONDS)) {
  2. // 指定等待时间3秒内获取到许可:
  3. try {
  4. // TODO:
  5. } finally {
  6. semaphore.release();
  7. }
  8. }

Semaphore本质上就是一个信号计数器,用于限制同一时间的最大访问数量。

小结

如果要对某一受限资源进行限流访问,可以使用Semaphore,保证同一时间最多N个线程访问受限资源。

读后有收获可以支付宝请作者喝咖啡:

使用Semaphore - 图1