提前声明:本文仅仅提供自己学习使用 转自 毕小宝—线程池的饱和策略-Semaphore实现任务提交限制,
java并发编程实践阅读笔记之线程池的使用
当线程池的工作队列被填满后,如果没有预定义的饱和策略来阻塞任务的执行,则可以通过信号量Semaphore来限制任务的到达率。Semaphore是一个同步工具类,用来控制同时访问某个特定资源的操作数量。它的acquire方法返回一个虚拟的许可,如果没有可用的许可,则阻塞该方法的调用线程直到有可用许可为止。如果线程池使用无界队列缓冲任务时,如果任务在某一时间增长数量过快,容易导致内存耗尽。
无界队列和Semaphore搭配使用,通过设置信号量的上界,来控制任务的提交速率。使用上一章的MyCommand任务,结合Semaphore,代码如下:
/**
*
* @title :BoundedExecutor
* @description :使用Semaphore控制任务的提交速率
* @since :2014-12-15
*/
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec,int bound){
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command) throws InterruptedException{
try{
semaphore.acquire();
exec.execute(new Runnable(){
@Override
public void run() {
try{
command.run();
}finally{
System.out.println("执行完成 ,release...");
semaphore.release();
}
}
});
}catch(RejectedExecutionException e){
System.out.println("队列已满,拒绝执行");
semaphore.release();
}
}
public static void main(String[] args) {
//虽然线程池大小为4,但是Semaphore限制每次只能有两个任务被执行
Executor exec = Executors.newCachedThreadPool();
BoundedExecutor b = new BoundedExecutor(exec,2);
MyCommand c1 = new MyCommand("c1");
MyCommand c2 = new MyCommand("c2");
MyCommand c3 = new MyCommand("c3");
MyCommand c4 = new MyCommand("c4");
MyCommand c5 = new MyCommand("c5");
try {
b.submitTask(c1);
b.submitTask(c2);
b.submitTask(c3);
b.submitTask(c4);
b.submitTask(c5);
} catch (InterruptedException execption) {
execption.printStackTrace();
}
}
}
执行结果:
pool-1-thread-2 ,name: c2,Mon Dec 15 16:20:17 CST 2014
pool-1-thread-1 ,name: c1,Mon Dec 15 16:20:17 CST 2014
执行完成 ,release...
执行完成 ,release...
pool-1-thread-1 ,name: c4,Mon Dec 15 16:20:22 CST 2014
pool-1-thread-3 ,name: c3,Mon Dec 15 16:20:22 CST 2014
执行完成 ,release...
执行完成 ,release...
pool-1-thread-1 ,name: c5,Mon Dec 15 16:20:27 CST 2014
执行完成 ,release...
执行结果分析:使用Semaphore限制每次只能提交两个任务,任务完成后释放信号量许可,的确可以控制任务的提交速率。