Java TimerTask在一段时间后超时

问题描述

我有一个timer定期运行的timerTask,但有时会卡住(不会失败或给出任何异常)。

因此,此任务的下一个迭代不会因为上一个任务卡住而开始。

我希望任务完成:

  1. 一段时间后,要么超时(以便下次迭代开始)。
  2. 或者即使下一个迭代正在运行,也要开始下一个迭代,这会强制取消任何先前正在运行的任务。

下面是我的代码:

    private static Timer timer = new Timer();

    private static TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {

            try{
                aSeparateMethodWhichGetsStuckOccasionally();

            }catch (Exception exception){
                logger.info(">>> Exception : " + exception);
            }

        }
    };
    
    public static void scheduleTask() {
        
        initialDelay = 600000;
        gap = 600000;

        timer.scheduleAtFixedRate(timerTask,initialDelay,gap);
    }

解决方法

首先,必须编写aSeparateMethodWhichGetsStuckOccasionally(),以便它可以正确响应中断。中断是停止许多操作的唯一方法。

如果该方法正在捕获InterruptedException,请完全删除try / catch,然后将throws InterruptedException添加到方法声明中。如果该方法包含任何catch (Exception)子句,则必须检查InterruptedException并在这种情况下终止,或者更好的是,更改子句以仅捕获您绝对需要捕获的异常,不包括InterruptedException。 (捕获Exception是一个坏习惯。大多数未经检查的异常都存在,它们暴露了程序员的错误,应该纠正而不是隐藏它们。NullPointerException和IndexOutOfBoundsException是此类异常的示例。)

这将使中断该方法成为可能。然后,您可以使用ExecutorService.invokeAll对其执行超时:

private static final ExecutorService executor =
    Executors.newSingleThreadExecutor();

public static TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        try {

            Callable<Void> subtask = () -> {
                aSeparateMethodWhichGetsStuckOccasionally();
                return null;
            };

            List<Future<Void>> futures =
                executor.invokeAll(Collections.singleton(subtask),gap,TimeUnit.MILLISECONDS);

            Future<?> future = futures.get(0);
            if (!future.isCancelled()) {
                // Check if subtask threw an exception.
                future.get();
            }

        } catch (Exception exception) {
            logger.log(Level.INFO,">>> Exception: " + exception,exception);
        }
    }
};

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...