这是关于Java的内置Timer类的。我需要以一定的设置间隔频繁调用一个方法,但是如果执行时间太长,我不希望它们堆积,因此解决方案是在所述方法的开头将下一个执行排队。当然,这意味着排队发生在同一队列线程中。这会解决还是会引起问题?
public class SomeClass extends TimerTask {
public static SomeClass timer;
public void run() {
timer.schedule(this,100);
//do stuff
}
}
最佳答案
Java具有执行程序服务来执行您想做的事情。看看方法ScheduledExecutorService#scheduleWithFixedDelay()。与方法ScheduledExecutorService#scheduleAtFixedRate()相反,具有固定延迟的方法不会尝试跟上。
这是一个例子:
public void run() {
Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(
this::task, 0, 10, TimeUnit.MILLISECONDS);
}
public void task() {
// run your task
}
确实,您的用例似乎未包含在标准库方法中。但是,您应该可以使用以下类来完成所需的操作。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class TimerExample {
private final ScheduledExecutorService executor = Executors
.newSingleThreadScheduledExecutor();
private final Runnable task;
private final Consumer<Exception> onException;
private final long delay;
private final TimeUnit unit;
public TimerExample(Runnable task, Consumer<Exception> onException,
long delay, TimeUnit unit) {
this.task = task;
this.onException = onException;
this.delay = delay;
this.unit = unit;
}
public void start() {
executor.execute(this::execute);
}
private void execute() {
executor.schedule(this::execute, delay, unit);
try {
task.run();
} catch (Exception e) {
onException.accept(e);
}
}
}
这是用法:
new TimerExample(() -> System.out.println("."),
Exception::printStackTrace, 20, TimeUnit.MILLISECONDS).start();
由于它使用单线程执行程序服务,因此在上一个执行完成之前,它不会启动下一个执行。同样,它在任务本身执行之前计划下一次执行。
另外,请参见this SO-疑问,有关为什么您应该首选Timer类之上的执行程序服务。
您仍然必须自己实现关闭机制。