Java 线程池关闭
Posted Mercy互动分享
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 线程池关闭相关的知识,希望对你有一定的参考价值。
虽然使用ExecutorService可以让线程处理变的很简单,可是有没有人觉得在结束线程运行时候只调用shutdown方法就可以了?
实际上,只调用shutdown方法的是不够的。我们用学校的老师和学生的关系来说明这个问题。
shutdown只是起到通知的作用
我们来假设如下场景:
学校里在课上老师出了一些问题安排全班同学进行解答并对学生说“开问题解答完毕后请举手示意!”
如果有学生解答完毕后会举手对老师说“老师我做完了!”,如果大家都解题完毕后上课结束。
上面的场景对应于ExecutorService里的方法的话是下面的样子。
老师: ExecutorService
学生: ExecutorService里的线程
问题: 通过参数传递给ExecutorService.execute的任务(Runnable)
授课: main线程
学校: Java进程
“问题解答完毕后请举手示意!”是shutdown方法。“老师我做完了!”是各个任务(Runnable)的运行结束。
所有的任务(Runnable)都结束了的话main线程(授课)也结束了。
在这里,我们假设试卷中有难度较大的问题,当然学生解答较难的问题也会比较花时间。
在上面的场景中老师除了shutdown方法之外什么也做不了,只能呆呆得等着学生们说,“老师我做完了!”之后才可以有下一步动作。
这都是因为shutdown方法只是用来通知的方法。
这时如果即使授课时间结束(main线程结束),学校也不能放学(Java进程结束),因为学生们还在解题中呢。这个时候如果你是老师你会怎么做?
一般的情况肯定是经过一定的时间在授课快要结束的时候,如果还有人没有解答出来的话,或者公布给大家解题方法,
或者作为课后习题让学生回去继续思考,然后结束上课对不对!
定好下课时间后等待结束
如果经过了一定的时间任务(Runnable)还不结束的时候我们可以通过中止任务(Runnable)的执行,以防止一直等待任务的结束。
awaitTermination方法正是可以实现这个中止作用的角色。
具体的使用方法是,在shutdown方法调用后,接着调用awaitTermination方法。这时只需要等待awaitTermination方法里第一个参数指定的时间。
如果在指定的时间内所有的任务都结束的时候,返回true,反之返回false。返回false意味着课程结束的时候还有题目没有解答出来的学生。
通过shutdownNow方法,我们可以作为老师向同学发出“没有解答出来的同学明天给出解答”的命令后结束授课。
shutdownNow方法的作用是向所有执行中的线程发出interrupted以中止线程的运行。这时,各个线程会抛出InterruptedException异常(前提是
线程中运行了sleep等会抛出异常的方法)
目前根据该翻译文档,在项目中的代码示例(定时执行的线程池)--
private void updateScheduleCallTms(WmsDepartureRegister departureRegister, String vehicle, SysUser sysUser) {
ScheduledExecutorService scheduledExecutorService = null;
try {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
//开启定时线程调用tms
ScheduledExecutorService finalScheduledExecutorService = scheduledExecutorService;
scheduledExecutorService.scheduleAtFixedRate(() -> {
List<WmsCqinboundTms> lastWmsCqinboundTms = getLastWmsCqinboundTms(vehicle);
if (CollectionUtils.isNotEmpty(lastWmsCqinboundTms)) {
WmsCqinboundTms tms = lastWmsCqinboundTms.get(0);
if (!Objects.equals(tms, null) && tms.getTmsInnvocationCount() < CALL_TMS_COUNT) {
tms.setId(null);
tms.setGmtUpdate(new Date());
tms.setGmtCreate(new Date());
if (sysUser != null) {
tms.setCreateUserName(sysUser.getName());
tms.setModifyUserName(sysUser.getName());
}
tms.setTmsInnvocationCount(tms.getTmsInnvocationCount() + 1);
String result = null;
try {
result = callTms(vehicle, WmsFetchFromTmsTypeEnum.INBOUND.getValue(), WhCodeEnum.UNLCN_XN_CQ.getText());
} catch (Exception e) {
LOGGER.error("GateControllerServiceImpl.addOutboundOpenByHm error:", e);
result = "{\n" +
" \"success\": false,\n" +
" \"records\": null,\n" +
" \"message\": \"调用tms接口超时失败!\"\n" +
"}";
}
if (StringUtils.isNotBlank(result)) {
JSONObject jsonObject = JSONObject.parseObject(result);
String msg = jsonObject.getString("message");
String records = jsonObject.getString("records");
Boolean success = jsonObject.getBoolean("success");
if (success) {
//更新数据为成功
tms.setTmsResult(String.valueOf(Boolean.TRUE));
List<WmsFecthInboundFromTmsBO> parseArray = JSONArray.parseArray(records, WmsFecthInboundFromTmsBO.class);
if (CollectionUtils.isNotEmpty(parseArray)) {
insertWmsCqInboundTms(sysUser, parseArray, WmsSysSourceEnum.WMS_CREATE.getValue());
departureRegister.setDispatchNo(parseArray.get(0).getShipno());
wmsDepartureRegisterMapper.updateByPrimaryKeySelective(departureRegister);
}
} else {
LOGGER.error("GateControllerServiceImpl.addOutboundOpenByHm error", msg);
//再调用tms 4次
result = "{\n" +
" \"success\": false,\n" +
" \"records\": null,\n" +
" \"message\": \"" + msg + "!\"\n" +
"}";
tms.setTmsResult(String.valueOf(Boolean.FALSE));
}
}
wmsCqinboundTmsMapper.insertSelective(tms);
//保存对应的日志表
insertTmsLogAndTime(vehicle, result);
} else if (!Objects.equals(tms, null) && tms.getTmsInnvocationCount() >= CALL_TMS_COUNT) {
finalScheduledExecutorService.shutdown();
}
}
}, 0, 2, TimeUnit.MINUTES);
} catch (Exception e) {
LOGGER.error("WmsCQInboundServiceImple.updateScheduleCallTms 执行失败 error:", e);
} finally {
try {
if (scheduledExecutorService != null) {
scheduledExecutorService.shutdown();
if (!scheduledExecutorService.awaitTermination(5, TimeUnit.MINUTES)) {
scheduledExecutorService.shutdownNow();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (scheduledExecutorService != null) {
scheduledExecutorService.shutdownNow();
}
}
}
}
以上是关于Java 线程池关闭的主要内容,如果未能解决你的问题,请参考以下文章
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段