Java线程中的计时器

时间:2012-07-29 06:02:41

标签: java multithreading timer

我有一个负责做某些过程的线程。我希望这样做,以便这些处理每3秒完成一次。我已经使用了下面的代码,但是当线程启动时,没有任何反应。 我假设当我为我的计时器定义一个任务时,它会在时间间隔内自动执行ScheduledTask,但它根本不做任何事情。 我错过了什么?

class temperatureUp extends Thread 
{
    @Override
    public void run()
    {
    TimerTask increaseTemperature = new TimerTask(){

        public void run() {
        try {
            //do the processing 
        } catch (InterruptedException ex) {}
        }
    };

    Timer increaserTimer = new Timer("MyTimer");
    increaserTimer.schedule(increaseTemperature, 3000);

    }
};

5 个答案:

答案 0 :(得分:19)

您的代码段中有一些错误:

  • 你扩展了Thread课程,这不是一个很好的练习
  • Timer内有Thread?这不合理,因为Timer自行运行Thread

您应该(在需要的时候/在必要时)实现Runnable,请参阅here作为简短示例,但我看不出需要Thread和{{1}在你给的片段中。

请参阅下面的工作Timer的示例,它将在每次调用时将计数器增加1(每3秒):

Timer

<强>附录:

我做了一个简单的例子,将import java.util.Timer; import java.util.TimerTask; public class Test { static int counter = 0; public static void main(String[] args) { TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("TimerTask executing counter is: " + counter); counter++;//increments the counter } }; Timer timer = new Timer("MyTimer");//create a new Timer timer.scheduleAtFixedRate(timerTask, 30, 3000);//this line starts the timer at the same time its executed } } 纳入混音中。所以现在Thread只会每隔3秒将TimerTask增加1,counter每次检查计数器时都会显示Thread值休眠1秒(它会在counter)之后终止自身和计时器:

counter==3

答案 1 :(得分:3)

import java.util.Timer;
import java.util.TimerTask;

public class ThreadTimer extends TimerTask{
    static int counter = 0;

    public static void main(String [] args) {
        Timer timer = new Timer("MyTimer");
        timer.scheduleAtFixedRate(new ThreadTimer(), 30, 3000);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("TimerTask executing counter is: " + counter);
        counter++;
   }

}

答案 2 :(得分:2)

为了每隔三秒钟执行一次操作,您应该使用scheduleAtFixedRate(请参阅javadoc)。

但是你的代码实际上什么也没做,因为你创建了一个线程,你可以在线程运行停止之前启动一个计时器(没有更多事情要做)。当计时器(单次射击)触发时,没有线程中断(之前运行完毕)。

class temperatureUp extends Thread 
{
    @Override
    public void run()
    {
    TimerTask increaseTemperature = new TimerTask(){

        public void run() {
        try {
            //do the processing 
        } catch (InterruptedException ex) {}
        }
    };

    Timer increaserTimer = new Timer("MyTimer");
    //start a 3 seconds timer 10ms later
    increaserTimer.scheduleAtFixedRate(increaseTemperature, 3000, 10);

    while(true) {
         //give it some time to see timer triggering
         doSomethingMeaningful();
    }
}

答案 3 :(得分:1)

我认为您使用的方法有签名schedule(TimerTask task, long delay)。所以实际上你只是推迟了ONLY执行的开始时间。

要将其安排为每3秒运行一次,您需要使用此方法schedule(TimerTask task, long delay, long period),其中第三参数用于给出句点间隔。

您可以在此处参考Timer类定义以获得进一步的帮助

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html

答案 4 :(得分:1)

TimerTimerTask 是旧版

TimerTimerTask 类现在是 legacy。要在特定时间运行代码或重复运行代码,请使用 scheduled executor service

引用 Timer 类 Javadoc:

<块引用>

Java 5.0 引入了 java.util.concurrent 包,其中的并发实用程序之一是 ScheduledThreadPoolExecutor,它是一个线程池,用于以给定的速率或延迟重复执行任务。它实际上是 Timer/TimerTask 组合的更通用的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化 TimerTask(只需实现 Runnable)。将 ScheduledThreadPoolExecutor 配置为一个线程使其等效于 Timer。

执行器框架

在现代 Java 中,我们使用 Executors framework 而不是直接寻址 Thread 类。

将您的任务定义为 RunnableCallable。您可以使用如下所示的紧凑 lambda 语法。或者,您可以使用常规语法来定义实现 Runnable(或 Callable)接口的类。

请求一个 ScheduledExecutorService 对象每隔一段时间执行一次您的 Runnable 对象的代码。

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;

Runnable task = () -> { 
    System.out.println( "Doing my thing at: " + Instant.now() );
};

long initialDelay = 0L ; 
long period = 3L ;
TimeUnit timeUnit = TimeUnit.SECONDS ;
scheduledExecutorService.submit( task , initialDelay, period , timeUnit ) ;

…
scheduledExecutorService.shutdown() ;  // Stops any more tasks from being scheduled.
scheduledExecutorService.awaitTermination() ;  // Waits until all currently running tasks are done/failed/canceled. 

请注意,我们没有直接管理上述代码中的任何 Thread 对象。管理线程是执行器服务的工作。

提示:

  • 当不再需要或当您的应用退出时,始终优雅地关闭您的执行程序服务。否则后备线程池可能会像僵尸?‍♂️一样无限期地继续下去。
  • 考虑将任务的工作代码包装在 try-catch 中。任何到达预定执行程序服务的未捕获异常或错误都会导致以静默方式停止进一步调度任何更多运行。