我们在开发过程中,在进行时间操作时,如果在规定的时间内完成处理的话,有可能会回到正确的结果。否则,就会被视为超时任务。此时,我们不再等待(不再执行)的时间操作,直接向调用者传达这个任务需要时间,被取消了。
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
暂无评论内容