前段时间看了写并发编程相关的一些文章,感觉收益颇多,赶紧记录下来。虽然工作中很少能接触到这样的场景,但是学习的脚步不能停下来! Come on !
信号量模型可以简单理解为三个操作:一个计数器、一个等待队列、三个方法。在信号量模型里。计数器和等待队列对外是透明的,所以只能通过信号量模型提供的三个方法来访问他们。这三个方法可以理解为: init()、down()、up()。 可以通过一张图片看一下。
init(): 设置计数器的初始值
down(): 计数器的值减1;如果此时计数器的值小于0,则当前线程被阻塞,否则当前线程可以继续执行。
up(): 计数器的值加1;如果此时计数器的值小于或者等于0,则唤醒等待队列中的一个线程,并将其从等待队列中移除。
这三个方法都是原子性的,并且都是由信号量模型方法实现保证的。java中的对应的类为Semaphore。 个人理解Semaphore有两个核心的方法:
acquire():获取一个许可,标识该线程可以执行(对应的前面说到的init()方法)。 release(): 归还一个许可(对应前面说到的down()方法)。
用Semaphore实现一个简单限流器:
场景:创建一个对象池,一次性创建N个对象,之后所有的线程重复利用这N个对象,当然对象被释放前,也是不允许其他线程使用的。代码如下:
/**
* @Description: 对象池,只允许 size个数量线程同时使用对象,可以重复使用对象。可以达到限流效果
* @author: ListenerSun(男, 未婚) 微信:810548252
* @Date: Created in 2019-12-09 23:23
*/
public class ObjectPool<T,R> {
/**
*对象集合
*/
final List<T> pool;
/**
* 信号量 控制 同时使用对象 的线程个数
*/
final Semaphore sem;
public ObjectPool(int size,T t) {
pool = new Vector<>();
for(int i = 0; i < size; i++){
pool.add(t);
}
sem = new Semaphore(size);
}
R excute(Function<T,R> function) throws InterruptedException {
T t = null;
sem.acquire();
try{
t = pool.remove(0);
return function.apply(t);
}finally {
pool.add(t);
sem.release();
}
}
}