2016-02-13 74 views
0

这是关于java的内置Timer类的。我需要一个方法在特定的时间间隔内被频繁地调用,但是如果执行时间太长,我不希望它们堆积起来,所以解决方法是在所述方法的开始处排队下一个执行。当然这意味着排队发生在同一队列中。这会解决还是会导致问题?从定时器线程调用java定时器任务

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

} 

回答

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-有关为什么您应该更喜欢Timer类上方的执行程序服务的问题。

你还得自己实现关机机制。

+0

尽管scheduleWithFixedRate()在上一次执行完成后才启动下一次执行的计时器,但scheduleAtFixedRate()会聚集在一起。我搜索的是一种只聚集一次的方法,这样,如果一次执行时间过长(比如说太长时间),下一次执行会立即开始,但是之后的执行会在指定的延迟后触发,就像什么都没发生。 *示例:* 延迟:200 ms 执行[执行时间:10ms。开始:0ms] - >执行[花费:1000毫秒。开始:200ms] - >执行[花费:10毫秒。开始:1200ms] - >执行[花费:30ms。开始:1400ms] – Zain

+0

同时我自己写了一堂课,如果有人想看看它应该是完全安全的:http://pastebin.com/raw/jcUrtwC5 :) 我的用例是一个实时模拟使用时间步。顺便说一下,你正在使用C语法;) – Zain

+0

非常感谢你的回答,executor.schedule似乎能够处理Timer类无法处理的事情,这两个事情排队了同样的事情。我认为? – Zain