
我们在开发过程中,在进行时间操作时,如果在规定的时间内完成处理的话,有可能会回到正确的结果。否则,就会被视为超时任务。此时,我们不再等待(不再执行)的时间操作,直接向调用者传达这个任务需要时间,被取消了。
1、说明
java已经为我们提供了解决办法。jdk1.5带来的并发库Future类可以满足这一需求。Future类中重要的方法有get()和cancel()。get()获取数据对象,如果数据没有加载,则在获取数据之前堵塞,cancel()取消数据加载。另一个get(timeout)操作表明,如果timeout时间内没有得到,就会失败回来,不会堵塞。
利用泛型和函数式接口编写一个工具类,可以让超时处理更方便,而不用到处写代码。
2、实例
/**
*TimeoutUtil<br>
*
*@authorlys
*@date2021/2/25
*/
@Slf4j
@Component
@NoArgsConstructor
publicclassTimeoutUtil{
privateExecutorServiceexecutorService;
publicTimeoutUtil(ExecutorServiceexecutorService){
this.executorService=executorService;
}
/**
*有超时限制的方法
*
*@parambizSupplier业务函数
*@paramtimeout超时时间,ms
*@return返回值
*/
public<R>Result<R>doWithTimeLimit(Supplier<R>bizSupplier,inttimeout){
returndoWithTimeLimit(bizSupplier,null,timeout);
}
/**
*有超时限制的方法
*
*@parambizSupplier业务函数
*@paramdefaultResult默认值
*@paramtimeout超时时间,ms
*@return返回值
*/
public<R>Result<R>doWithTimeLimit(Supplier<R>bizSupplier,RdefaultResult,inttimeout){
Rresult;
StringerrMsg="Nullvalue";
FutureTask<R>futureTask=newFutureTask<>(bizSupplier::get);
executorService.execute(futureTask);
try{
result=futureTask.get(timeout,TimeUnit.MILLISECONDS);
}catch(InterruptedException|ExecutionException|TimeoutExceptione){
errMsg=String.format("doWithTimeLimit执行超过%d毫秒,强制结束",timeout);
log.error(errMsg,e);
futureTask.cancel(true);
result=defaultResult;
}
returnof(result,errMsg);
}
/**
*随机耗时的测试方法
*/
privateStringrandomSpentTime(){
Randomrandom=newRandom();
inttime=(random.nextInt(10)+1)*1000;
log.info("预计randomSpentTime方法执行将耗时:"+time+"毫秒");
try{
Thread.sleep(time);
}catch(Exceptione){
}
return"randomSpentTime-->"+time;
}
publicstaticvoidmain(String[]args)throwsException{
ExecutorServiceexecutorService=newThreadPoolExecutor(1,1,
0L,TimeUnit.MILLISECONDS,
newLinkedBlockingQueue<Runnable>(),
runnable->{
Threadthread=newThread(runnable);
//以守护线程方式启动
thread.setDaemon(true);
returnthread;
});
TimeoutUtiltimeoutUtil=newTimeoutUtil(executorService);
for(inti=1;i<=10;i++){
log.info("\n=============第{}次超时测试=============",i);
Thread.sleep(6000);
longstart=System.currentTimeMillis();
Stringresult=timeoutUtil.doWithTimeLimit(()->timeoutUtil.randomSpentTime(),5000).getOrElse("默认");
log.info("doWithTimeLimit方法实际耗时{}毫秒,结果:{}",System.currentTimeMillis()-start,result);
}
}
}原文来自:https://www.py.cn © 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
















































暂无评论内容