今天写了个超时重传的方法,用到了线程池,同时也记录一下踩过的坑。
当队列也满时执行的拒绝策略:
AbortPolicy (默认:抛出异常)
DiscardPolicy(丢弃新的任务)
DiscardOldestPolicy(丢弃旧的任务,保留新的任务)
CallerRunsPolicy(不丢弃,使用调用该线程池的线程去执行剩余的任务--主线程)
因为我使用的是CallerRunsPolicy这个策略,但是当我执行完一轮任务
之后,发现一直抛出如下异常:
Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]
嗯哼???,线程终止,无论再怎么执行都是抛出这个异常。。。就开始找原因了,一开始还以为是CallerRunsPolicy这个拒绝策略我理解的有问题。。。后面才发现原来是,我在finally中加入了
finally {
executorService.shutdownNow();//关闭线程池,关闭后使用不了线程池,直接执行拒绝策略
}
shutdown()原来这个方法是会关闭线程池的,后面就会直接执行拒绝策略。。。
后面查了下资料,如果线程池的核心线程数为0的时候,也会被动触发关闭线程池,但是这个需要手动设置可以回收核心线程才行。
贴上写的超时方法
public static String sendRequest(int overtime, int retryTimes, String requestType, String rawType, String url, Map<String, String> headerMap, Map<String, String> paramMap) throws Exception {
Callable<String> task = () -> {
//执行耗时代码
String result = "";
if (RouteConstants.ROUTE_POST.equalsIgnoreCase(requestType)) {
// post请求
result = HttpRequest.post(url).addHeaders(headerMap)
.body(buildBody(paramMap, rawType))
.execute().body();
} else if (RouteConstants.ROUTE_GET.equalsIgnoreCase(requestType)) {
// get请求
result = HttpRequest.get(PreHttpUtil.buildGetUrl(url, paramMap)).addHeaders(headerMap).execute().body();
}
return result;
};
Future<String> future = executorService.submit(task);
try {
//设置超时时间
String rst = future.get(overtime, TimeUnit.SECONDS);
return rst;
} catch (/*InterruptedException | ExecutionException | Timeout*/Exception e) {
retryTimes--;
if ( e instanceof TimeoutException) {
logger.info("===执行超时, url:{}--入参:{}===", url, paramMap);
if(retryTimes > 0){
sendRequest(overtime, retryTimes, requestType, rawType, url, headerMap, paramMap);
}
throw new Exception("execute request timed out");
}
throw e;
}/* finally {
executorService.shutdownNow();//关闭线程池,关闭后使用不了线程池,直接执行拒绝策略
}*/
}