并发编程【Semaphore】

一、使用场景

Semaphore 翻译成字面意思为 信号量Semaphore 可以控制同时访问的线程个数

通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

信号量主要用于两个目的:

  1. 用于多个共享资源的互斥使用;
  2. 用于并发线程数的控制。

二、代码实现

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);

        for(int i=1; i<=6; i++){
            new Thread(()->{
                try {
                    // 获取资源
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "抢占到了车位");
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName() + "离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放资源
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}

运行结果:

1抢占到了车位
3抢占到了车位
2抢占到了车位
2离开了车位
3离开了车位
1离开了车位
4抢占到了车位
6抢占到了车位
5抢占到了车位
6离开了车位
4离开了车位
5离开了车位

三、大致原理分析

acquire() :当一个线程调用acquire操作时,它要么成功获取信号量(同时信号量减1),要么一直等下去,直到有线程释放信号量,或超时。

release():实际上会将信号量的值加1,然后唤醒等待的线程。

四、特殊使用

当使用Semaphore semaphore = new Semaphore(1);代码创建建信号量时,实际上就相当于使用 synchronized 进行加锁。

五、其它 API 方法

// 用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可
public void acquire()
    
// 获取 permits 个许可    
public void acquire(int permits)

// 释放许可。注意,在释放许可之前,必须先获获得许可
public void release() 
    
// 释放 permits 个许可    
public void release(int permits)

上面 4 个方法都会被阻塞,如果想立即得到执行结果,可以使用下面几个方法:

// 尝试获取一个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false
public boolean tryAcquire():

// 尝试获取一个许可,若在指定的时间内获取成功,则立即返回 true,否则则立即返回 false
public boolean tryAcquire(long timeout, TimeUnit unit)
    
// 尝试获取 permits 个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false
public boolean tryAcquire(int permits):
    
// 尝试获取 permits个许可,若在指定的时间内获取成功,则立即返回 true,否则则立即返回 false
public boolean tryAcquire(int permits, long timeout, TimeUnit unit): 
    
// 得到可用的许可数目
public int availablePermits()

Java新手,若有错误,欢迎指正!

posted @ 2021-03-07 22:48  跑调大叔!  阅读(61)  评论(0编辑  收藏  举报