ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭

看到一个博客,如下
[url=http://bbs.csdn.net/topics/390268738]Java多线程-线程池ExecutorService.shutdown什么时候执行[/url]

其中问题:
ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭。
但是我用了计数信号量Semaphore后,发现线程还没有跑完,他就执行了shutdown().


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest extends Thread {
Semaphore position;
private int id;

public SemaphoreTest(int i, Semaphore s) {
this.id = i;
this.position = s;
}

public void run() {
try {
if (position.availablePermits() > 0) {
System.out.println("顾客[" + id + "]进入厕所,有空位");
} else {
System.out.println("顾客[" + id + "]进入厕所,没空位,排队");
}
position.acquire();
System.out.println("【" + id + "】acquire坑位");
Thread.sleep((int) (Math.random() * 1000));
System.out.println("【" + id + "】完毕release");
position.release();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String args[]) {
ExecutorService pool = Executors.newCachedThreadPool();
Semaphore position = new Semaphore(2); // 初始化两个空位
for (int i = 0; i < 5; i++) {
pool.submit(new SemaphoreTest(i, position));
}
System.out.println("开始释放线程池资源");
pool.shutdown();
System.out.println("完成释放线程池资源");
position.acquireUninterruptibly(2);
System.out.println("如厕完毕,清理厕所");
position.release(2);
}
}


PS:
1、代码中主线程并没有等待线程池执行完毕这一说,而是持续往下执行
2、至于信号量,只会在几个子线程之间发挥作用
3、主线程和线程池之间没有直接关系,线程池使用自己的线程。生命周期也相互独立。
4、shutdown()可以理解为:主线程要求线程池关闭,但不会为此等待线程池执行完毕。
5、实际发挥了等待作用的并不是线程池所提供的能力(当然线程池也确实提供了这类能力),而是:position.acquireUninterruptibly(2) 这句话。
shutdown() 作为函数,当然是立即执行,也即是不再接受新任务了;但是它即不会强行终止正在执行的任务,也不会取消已经提交的任务。也就是说之前提交的5个任务,仍然会执行完毕,且跟主线程生命周期无关,也就是即便你直接在后面写上: if (1==1) return; 来立即结束主函数,你也会发现线程池的5个任务会顺利执行完毕。
6、另一个长得很像的函数是:
shutdownNow(),这个函数比shutdown()更狠,两点:
1)、对于尚未执行的任务,全部取消掉;
2)、对于正在执行的任务,发出interrupt()。
不过程序因为在发生异常时没有正确释放信号量(应该放在finally块中释放),所以如果改为shutdownNow()会出问题:主线程死等。


[url=http://lavasoft.blog.51cto.com/62575/115112]Java5 并发学习[/url]
[url=http://www.cnblogs.com/wanqieddy/p/3853863.html]ExecutorService中submit和execute的区别[/url]
[url=http://wosyingjun.iteye.com/blog/2302628]java线程常见面试题[/url]
[url=http://yizhenn.iteye.com/blog/2303195]JAVA并发-显式锁(一)[/url]


	public List<DrugDpInfoVO> selectRecipeSumVO(final AlertMessageKeyword query, PageBreaker page, final Integer engineRunFlag) {
List<DrugDpInfoVO> list = optAlertmessageStatisticMapper.selectRecipeSumVO(this.getBaseDBName(), query, page, engineRunFlag);

if (null == list || list.isEmpty()) {
log.warn("无匹配记录");
return list;
}

//ExecutorService EXECUTORSERVICE = Executors.newFixedThreadPool(50);
List<Future<DrugDpInfoVO>> listFuture = new ArrayList<>();

try {
for (final DrugDpInfoVO e : list) {
Future<DrugDpInfoVO> future = EXECUTORSERVICE.submit(new Callable<DrugDpInfoVO>() {

@Override
public DrugDpInfoVO call() throws Exception {

DrugDpInfoVO drugDpInfoVO = optAlertmessageStatisticMapper.selectSingleRecipeSumVO(getBaseDBName(), query, e, engineRunFlag);
drugDpInfoVO.setAmount(e.getAmount());
return drugDpInfoVO;

}
});

listFuture.add(future);
}

list.clear();

for (Future<DrugDpInfoVO> future : listFuture) {
list.add(future.get());
}

} catch (Exception e) {
log.error(e.getMessage(), e);
}

return list;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值