简体   繁体   English

Java线程中的定时器

[英]Timer in Java Thread

I have a thread which is in charge of doing some processes.我有一个线程负责执行一些过程。 I want make it so that these processing would be done every 3 seconds.我想让这些处理每 3 秒完成一次。 I've used the code below but when the thread starts, nothing happens.我使用了下面的代码,但是当线程启动时,什么也没有发生。 I assumed that when I define a task for my timer it automatically execute the ScheduledTask within time interval but it doesn't do anything at all.我假设当我为我的计时器定义一个任务时,它会在时间间隔内自动执行ScheduledTask但它根本不做任何事情。 What am I missing?我错过了什么?

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);

    }
};

A few errors in your code snippet:您的代码片段中有一些错误:

  • You extend the Thread class, which is not really good practice您扩展了Thread类,这不是一个很好的做法
  • You have a Timer within a Thread ?你在一个Thread有一个Timer吗? That doesnt make sense as the a Timer runs on its own Thread .这没有意义,因为Timer在它自己的Thread上运行。

You should rather (when/where necessary), implement a Runnable see here for a short example, however I cannot see the need for both a Thread and Timer in the snippet you gave.您应该(何时/在必要时)实现一个Runnable请参见此处的简短示例,但是我看不到您提供的代码段中同时需要ThreadTimer

Please see the below example of a working Timer which will simply increment the counter by one each time it is called (every 3seconds):请参阅下面的工作Timer示例,它会在每次调用时(每 3 秒)简单地将计数器加 1:

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
    }
}

Addendum:附录:

I did a short example of incorporating a Thread into the mix.我做了一个将Thread合并到混合中的简短示例。 So now the TimerTask will merely increment counter by 1 every 3 seconds, and the Thread will display counter s value sleeping for 1 seconds every time it checks counter (it will terminate itself and the timer after counter==3 ):所以现在TimerTask只会每 3 秒将counter增加 1,并且Thread将在每次检查 counter 时显示counter的值休眠 1 秒(它会在counter==3之后终止自身和计时器):

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

public class Test {

    static int counter = 0;
    static Timer timer;

    public static void main(String[] args) {

        //create timer task to increment counter
        TimerTask timerTask = new TimerTask() {

            @Override
            public void run() {
                // System.out.println("TimerTask executing counter is: " + counter);
                counter++;
            }
        };

        //create thread to print counter value
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println("Thread reading counter is: " + counter);
                        if (counter == 3) {
                            System.out.println("Counter has reached 3 now will terminate");
                            timer.cancel();//end the timer
                            break;//end this loop
                        }
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });

        timer = new Timer("MyTimer");//create a new timer
        timer.scheduleAtFixedRate(timerTask, 30, 3000);//start timer in 30ms to increment  counter

        t.start();//start thread to display counter
    }
}
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++;
   }

}

In order to do something every three seconds you should use scheduleAtFixedRate (see javadoc ).为了每三秒做一些事情,你应该使用 scheduleAtFixedRate (参见javadoc )。

However your code really does nothing because you create a thread in which you start a timer just before the thread's run stops (there is nothing more to do).但是,您的代码实际上什么都不做,因为您创建了一个线程,在该线程中您在线程运行停止之前启动了一个计时器(没有什么可做的了)。 When the timer (which is a single shoot one) triggers, there is no thread to interrupt (run finished before).当定时器(单发)触发时,没有线程可以中断(运行完成之前)。

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();
    }
}

I think the method you've used has the signature schedule(TimerTask task, long delay) .我认为您使用的方法具有签名schedule(TimerTask task, long delay) So in effect you're just delaying the start time of the ONLY execution.所以实际上你只是延迟了 ONLY 执行的开始时间。

To schedule it to run every 3 seconds you need to go with this method schedule(TimerTask task, long delay, long period) where the third param is used to give the period interval.要安排它每 3 秒运行一次,您需要使用此方法schedule(TimerTask task, long delay, long period)其中第三个参数用于给出周期间隔。

You can refer the Timer class definition here to be of further help您可以在此处参考 Timer 类定义以提供进一步帮助

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

Timer & TimerTask are legacy TimerTimerTask是遗留的

The Timer & TimerTask classes are now legacy . TimerTimerTask类现在是旧的 To run code at a certain time, or to run code repeatedly, use a scheduled executor service .要在特定时间运行代码,或重复运行代码,请使用预定的执行程序服务

To quote the Timer class Javadoc:引用Timer类 Javadoc:

Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. Java 5.0 引入了 java.util.concurrent 包,其中的并发实用程序之一是 ScheduledThreadPoolExecutor,它是一个线程池,用于以给定的速率或延迟重复执行任务。 It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable).它实际上是 Timer/TimerTask 组合的更通用的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化 TimerTask(只需实现 Runnable)。 Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.使用一个线程配置 ScheduledThreadPoolExecutor 使其等效于 Timer。

Executor framework执行器框架

In modern Java, we use the Executors framework rather than directly addressing the Thread class.在现代 Java 中,我们使用Executors 框架而不是直接寻址Thread类。

Define your task as a Runnable or Callable .将您的任务定义为RunnableCallable You can use compact lambda syntax seen below.您可以使用下面看到的紧凑 lambda 语法。 Or you can use conventional syntax to define a class implementing the Runnable (or Callable ) interface.或者,您可以使用传统语法来定义实现Runnable (或Callable )接口的类。

Ask a ScheduledExecutorService object to execute your Runnable object's code every so often.要求ScheduledExecutorService对象每Runnable执行您的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. 

Notice that we are not directly managing any Thread objects in the code above.请注意,我们没有直接管理上面代码中的任何Thread对象。 Managing threads is the job of the executor service.管理线程是执行程序服务的工作。

Tips:提示:

  • Always shutdown your executor service gracefully when no longer needed, or when your app exits.当不再需要或当您的应用程序退出时,始终优雅地关闭您的执行程序服务。 Otherwise the backing thread pool may continue indefinitely like a zombie 🧟‍♂️.否则后备线程池可能会像僵尸🧟‍♂️一样无限期地继续下去。
  • Consider wrapping your task's working code in a try-catch.考虑将任务的工作代码包装在 try-catch 中。 Any uncaught exception or error reaching the scheduled executor service results in silently halting the further scheduling of any more runs.任何未捕获的异常或错误到达预定的执行程序服务都会导致静默停止任何更多运行的进一步调度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM