@Slf4j
@Component
@NoArgsConstructor
public class TimeoutUtil {
private ExecutorService executorService;
public TimeoutUtil(ExecutorService executorService) {
this
.executorService = executorService;
}
public <R> Result<R> doWithTimeLimit(Supplier<R> bizSupplier, int timeout) {
return
doWithTimeLimit(bizSupplier,
null
, timeout);
}
public <R> Result<R> doWithTimeLimit(Supplier<R> bizSupplier, R defaultResult, int timeout) {
R result;
String errMsg =
"Null value"
;
FutureTask<R> futureTask =
new
FutureTask<>(bizSupplier::get);
executorService.execute(futureTask);
try
{
result = futureTask.get(timeout, TimeUnit.MILLISECONDS);
}
catch
(InterruptedException | ExecutionException | TimeoutException e) {
errMsg = String.format(
"doWithTimeLimit执行超过%d毫秒,强制结束"
, timeout);
log.error(errMsg, e);
futureTask.cancel(
true
);
result = defaultResult;
}
return
of(result, errMsg);
}
private String randomSpentTime() {
Random random =
new
Random();
int time = (random.nextInt(10) + 1) * 1000;
log.info(
"预计randomSpentTime方法执行将耗时: "
+ time +
"毫秒"
);
try
{
Thread.sleep(time);
}
catch
(Exception e) {
}
return
"randomSpentTime --> "
+ time;
}
public static void main(String[] args) throws Exception {
ExecutorService executorService =
new
ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new
LinkedBlockingQueue<Runnable>(),
runnable -> {
Thread thread =
new
Thread(runnable);
thread.setDaemon(
true
);
return
thread;
});
TimeoutUtil timeoutUtil =
new
TimeoutUtil(executorService);
for
(int i = 1; i <= 10; i++) {
log.info(
"\n=============第{}次超时测试============="
, i);
Thread.sleep(6000);
long start = System.currentTimeMillis();
String result = timeoutUtil.doWithTimeLimit(() -> timeoutUtil.randomSpentTime(), 5000).getOrElse(
"默认"
);
log.info(
"doWithTimeLimit方法实际耗时{}毫秒,结果:{}"
, System.currentTimeMillis() - start, result);
}
}
}