是否存在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"
消息。
答案 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()
的调用将永远被阻止。如果任务只计划运行一次,这可能会造成混乱,因为没人希望取消该任务。