阻止相当于Java的Timer

时间:2018-06-17 00:01:11

标签: java

是否存在java.util.Timer类的阻塞等价物?我正在寻找能够阻止创建计时器的线程的解决方案。

以下代码是非阻塞的,并且会立即打印"After timer"输出。

    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println("Hello");
        }
    }, 1000, 1000);
    System.out.println("After timer");

我想要实现的是仅在取消定时器时(以及取消定时器后)打印"After timer"消息。

2 个答案:

答案 0 :(得分:4)

暂且不说这听起来像是一件奇怪的事情......并且阻止线程是浪费的......

我不知道会执行此操作的标准Java API。

由于Timer不是final类,您可以使用覆盖扩展类以使用调度方法来实现阻塞行为,并使用将(也)取消阻塞任何方法来覆盖取消方法。线程。像这样:

    public class MyTimer extends Timer {

        private final Object lock = new Object();
        private boolean canceled = false;

        @Override
        public void schedule(TimerTask task, long delay) {
            synchronize (lock) {
                super.schedule(task, delay);
                while (!cancelled) {
                    lock.wait();
                }
            }
        }

        // and more schedule overrides ...

        @Override
        public void cancel() {
            synchronize (lock) {
                super.cancel();
                canceled = true;
                lock.notifyAll();
            }
        }
    }

请注意cancel()的行为类似于标准Timer::cancel方法。

  • 计划任务已取消。
  • 如果任务正在执行,则允许其完成。
  • 取消呼叫不等待任务完成
  • 取消Timer后,它将不再接受任何其他任务。

最后,请注意

new MyTimer().schedule(new TimerTask() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
}, 1000, 1000);

(使用阻止计划方法)无法解除阻止。必须将MyTimer实例发布到不同的线程,以便该线程可以在其上调用cancel()

答案 1 :(得分:2)

如果您希望有一个“ waitable” TimerTask,您可以在其中选择等待它被取消,那么下面的类引入了await()方法,该方法允许调用者等待计时器任务被取消。

abstract class WaitableTimerTask extends TimerTask {

    private final CountDownLatch countDownLatch = new CountDownLatch(1);

    @Override
    public boolean cancel() {
        boolean result = super.cancel();
        countDownLatch.countDown();
        return result;
    }

    public void await() throws InterruptedException {
        countDownLatch.await();
    }
}

您可以通过类似的方式使用它

public static void main(String[] args) throws InterruptedException {

    final WaitableTimerTask waitableTimerTask = new WaitableTimerTask(){
        @Override
        public void run() {
            System.out.println("TimerTask was run.");
        }
    };
    new Timer(true).schedule(waitableTimerTask, 1000, 1000);
    // Some other thread will need to cancel it.
    waitableTimerTask.await();
    System.out.println("TimerTask was canceled.");
}

也就是说,如果从不取消WaitableTimerTask,对await()的调用将永远被阻止。如果任务只计划运行一次,这可能会造成混乱,因为没人希望取消该任务。