理解高并发(12).限定并发个数_semaphore信号量

来源:互联网 发布:ubuntu怎么删除目录 编辑:程序博客网 时间:2024/05/20 16:40
概念 :
Semaphore 控制允许最大并发执行线程数, 当达到设置阀值后,阻塞,否则放行。
对应的函数:
//构造最大允许6个并发的线程许可
Semaphore semp = new Semaphore(6);
//获得到许可, 可用许可数-1
semp.acquire();
//释放许可, 可用许可 + 1
semp.release();

原理:
从待执行线程队列中获取线程后,利用CAS机制不断的比较当前许可是否小于预设的许可,如果小于则直接从队列中获取到的线程。
适用场景:
适用于线程池、资源池,限流相关场景。

示例代码:
一次仅允许6个客户到柜台操作。
public class SemaphoreTest {
static List<Thread> pool = new ArrayList<Thread>();
public static void main(String[] args) {
final Semaphore semp = new Semaphore(6);
final Bank bank = new Bank();
Thread[] threads = new Thread[20];
for(int i=0; i<20; i++){
Thread t = new Thread(new Runnable(){
public void run(){
try {
semp.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
SemaphoreTest.pool.add(Thread.currentThread());
bank.withDraw();
SemaphoreTest.pool.remove(Thread.currentThread());
semp.release();
}
}, "thread_" + i);
threads[i] = t;
t.start();
}
for(Thread t: threads){
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("============over=========");
}
}

class Bank{
public void withDraw(){
System.out.println(SemaphoreTest.pool.size());
System.out.println(Thread.currentThread().getName() + " begin存款");
Random ra =new Random();
try {
Thread.sleep(ra.nextInt(8000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 结束存款");
}
}