【问题标题】:Java TimerTask to timeout after sometimeJava TimerTask 在某个时间后超时
【发布时间】:2020-12-23 15:44:20
【问题描述】:

我有一个定期运行的 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);
    }

【问题讨论】:

  • 如果您深入了解您的任务卡住的原因并解决它们,而不是在其中堆积更多的东西可能会卡住,这不是更好吗?

标签: java multithreading timer scheduling timertask


【解决方案1】:

首先,你必须写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);
        }
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 2020-04-15
    • 2010-10-25
    相关资源
    最近更新 更多