Java线程超时自动重启的实现方案
方案一:使用ScheduledExecutorService结合Future
这是一个优雅且可控的方案,通过调度器来管理线程的生命周期。
public class ScheduledTimeoutThread {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private final ExecutorService executor = Executors.newSingleThreadExecutor();
public void executeWithTimeout(Runnable task, long timeout, TimeUnit unit) {
Future<?> future = executor.submit(task);
// 调度检查任务是否超时
scheduler.schedule(() -> {
if (!future.isDone()) {
future.cancel(true); // 取消当前任务
// 启动新任务
executeWithTimeout(task, timeout, unit);
}
}, timeout, unit);
}
}
这种方案的优点是:
- 可以精确控制超时时间
- 支持优雅的任务取消
- 资源管理更加可控
方案二:使用CompletableFuture结合超时控制
这个方案利用了Java 8引入的CompletableFuture,提供了更现代的异步编程模型。
public class CompletableFutureTimeoutThread {
public void executeWithTimeout(Runnable task, long timeout, TimeUnit unit) {
CompletableFuture.runAsync(task)
.orTimeout(timeout, unit)
.exceptionally(throwable -> {
if (throwable instanceof TimeoutException) {
// 超时后重新启动任务
executeWithTimeout(task, timeout, unit);
}
return null;
});
}
}
这种方案的特点是:
- 代码更加简洁
- 支持更丰富的异步操作组合
- 异常处理更加灵活
方案三:使用Timer实现定时检查
这是一个相对传统的方案,使用Timer来进行超时检测。
public class TimerTimeoutThread {
private static class TimeoutTask {
private Thread thread;
private boolean finished = false;
public void execute(Runnable task, long timeout) {
Timer timer = new Timer(true);
thread = new Thread(() -> {
try {
task.run();
finished = true;
} catch (Exception e) {
e.printStackTrace();
}
});
timer.schedule(new TimerTask() {
@Override
public void run() {
if (!finished) {
thread.interrupt();
// 启动新线程
new TimeoutTask().execute(task, timeout);
}
timer.cancel();
}
}, timeout);
thread.start();
}
}
}
这种方案适合:
- 简单的超时检测场景
- 对精确度要求不高的情况
- 单任务执行的场景
方案四:增强版的线程池方案
这个方案通过自定义线程池来实现更完善的超时管理。
public class EnhancedTimeoutThreadPool extends ThreadPoolExecutor {
private final long timeout;
private final TimeUnit timeUnit;
public EnhancedTimeoutThreadPool(long timeout, TimeUnit timeUnit) {
super(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
this.timeout = timeout;
this.timeUnit = timeUnit;
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t instanceof TimeoutException) {
// 任务超时,重新提交
execute(r);
}
}
@Override
public void execute(Runnable command) {
super.execute(() -> {
Future<?> future = submit(command);
try {
future.get(timeout, timeUnit);
} catch (TimeoutException e) {
future.cancel(true);
throw e;
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
这种方案的优势在于:
- 可以统一管理多个需要超时控制的任务
- 提供了更完整的生命周期管理
- 易于扩展和监控
实践建议
在选择具体方案时,需要考虑以下因素:
- 性能要求
- 如果对性能要求较高,建议使用方案一或方案二
- 如果任务较为简单,方案三也是可行的
- 可靠性要求
- 需要高可靠性的场景,推荐使用方案四
- 对于关键业务,建议增加监控和告警机制
- 资源管理
// 示例:优雅关闭资源
public void shutdown() {
try {
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
- 异常处理
建议在所有方案中都实现完善的异常处理机制,比如:
- 记录任务执行状态
- 统计超时次数
- 设置重试上限