从计时器线程调用java Timer-Task

时间:2016-02-13 22:24:56

标签: java multithreading timer

这是关于java的内置Timer-class。我需要一个在某些设置间隔频繁调用的方法,但如果执行时间太长,我不希望它们堆积起来,所以解决方案是在所述方法的开头排队下一次执行。当然这意味着排队发生在同一队列Thread中。这会成功还是会导致问题?

public class SomeClass extends TimerTask {
   public static SomeClass timer;
   public void run() {
      timer.schedule(this,100);
      //do stuff
   }

}

1 个答案:

答案 0 :(得分:1)

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-question,了解为什么您应该更喜欢Timer类之上的执行程序服务。

您仍然需要自己实施关机机制。