介绍
Semaphore(计数信号量)是一个线程工具类,主要用于描述多线程争夺有限资源的场景。在Semaphore初始化时会传入一个最大的信号量数字,其他的线程可以通过同一Semaphore实例的acquire(count)
方法来获取信号量,成功获取的可以继续执行,没有获取到的需要在这里等待,以此来控制对有限资源的使用,信号量获取成功的线程在使用完资源后可以使用release(count)
方法释放获取到的信号量,供其他线程获取使用。
常用方法列表
//构造函数,以传入数字个信号量作为最大信号量初始化
Semaphore(int permits);
//构造函数,可以额外指定锁的类型,true为公平锁,false为非公平锁
Semaphore(int permits, boolean fair);
//获取一个信号量,否则等待
void acquire();
//获取 permits 个信号量,否则等待
void acquire(int permits);
//获取一个信号量,否则等待且不允许中断
void acquireUninterruptibly();
//获取 permits 个信号量,否则等待且不允许中断
void acquireUninterruptibly(int permits);
//尝试获取一个信号量,获取成功返回true
boolean tryAcquire();
//尝试获取一个信号量,直到出了指定的等待时间,获取成功返回true
boolean tryAcquire(long timeout, TimeUnit unit);
//尝试获取 permits 个信号量,获取成功返回true
boolean tryAcquire(int permits);
//尝试获取 permits 个信号量,直到出了指定的等待时间,获取成功返回true
boolean tryAcquire(int permits, long timeout, TimeUnit unit);
//释放一个获取的信号量
void release();
//释放 permits 个获取的信号量
void release(int permits);
//返回当前可用的信号量数目,此方法通常用于调试
int availablePermits();
//返回立即可用的所有许可个数,并且将可用许可置0
int drainPermits();
//判断是否存在等待获取信号量的线程
boolean hasQueuedThreads();
//获取等待获取信号量的线程数目
int getQueueLength();
应用示例
public class SemaphoreTest {
private static int SEM_MAX = 10;
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(SEM_MAX);
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.execute(new MyTask(semaphore,4));
pool.execute(new MyTask(semaphore,5));
pool.execute(new MyTask(semaphore,7));
System.out.println("主线程运行到这里");
pool.shutdown();
System.out.println("主线程运行结束");
}
static class MyTask implements Runnable{
private Semaphore semaphore; // 信号量
private int count; // 申请信号量的大小
public MyTask(Semaphore semaphore, int count) {
this.semaphore = semaphore;
this.count = count;
}
@Override
public void run() {
try {
//获取count个信号量,如果获取不到则等待
semaphore.acquire(count);
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+"获取到信号量:"+count);
Thread.sleep(3000);
System.out.println(thread.getName()+"运行结束");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放count个信号量
semaphore.release(count);
System.out.println(Thread.currentThread().getName()+"释放信号量:"+count);
}
}
}
}
运行结果
pool-1-thread-1获取到信号量:4
主线程运行到这里
pool-1-thread-2获取到信号量:5
主线程运行结束
pool-1-thread-1运行结束
pool-1-thread-2运行结束
pool-1-thread-2释放信号量:5
pool-1-thread-1释放信号量:4
pool-1-thread-3获取到信号量:7
pool-1-thread-3运行结束
pool-1-thread-3释放信号量:7