Semaphore
一个计数器、一个等待队列、三个方法
- init对应创建对象时初始化信号量new Semaphore(size),计数器的值就是限制进入临界资源的线程数;
- down对应semaphore.acquire()方法获取进入临界资源资格,计数器减一;
- up对应semaphore.release()方法,操作完临界资源,释放信号量,计数器加一;
执行流程:
- 线程获取到信号量->进入临界区域执行->执行完释放信号量;
- 线程获取信号量失败,计数器值为0->线程被阻塞,直到有线程释放信号量,唤醒阻塞线程;
特性:允许多个线程进入临界区
借助这个特性实现各种资源池、限流器
对象池实现:
/**
* 对象池
* @author zhan
* @version 2021/6/27
*/
public class ObPool<T, R> {
private final List<T> pool;
private final Semaphore semaphore;
public ObPool(T t, Integer size){
pool = new Vector<>();
for (int i = 0; i <size; i++) {
pool.add(t);
}
semaphore = new Semaphore(size);
}
public R exec(Function<T, R> func) throws InterruptedException {
T t = null;
semaphore.acquire();
try {
T remove = pool.remove(0);
if (remove == null){
throw new RuntimeException("empty pool!");
// 或者再次填充对象池
}
return func.apply(remove);
}finally {
semaphore.release();
pool.add(t);
}
}
@Override
public String toString(){
return pool.toString()+"\nsemaphore\navailablePermits:"+semaphore.availablePermits()+"drainPermits:"+semaphore.drainPermits()+"QueueLength:"+semaphore.getQueueLength();
}
}