23

我有一个负责执行某些进程的线程。我想让这些处理每 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);

    }
};
4

5 回答 5

26

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

  • 您扩展了Thread课程,这不是很好的做法
  • 你有一个Timer内一个Thread?这没有意义,因为 aTimer自己运行Thread

您应该(在必要时/在必要时)在此处Runnable实现一个简短的示例,但是我看不到您提供的代码段中需要 a和a 。ThreadTimer

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

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

附录:

我做了一个将 aThread加入到混合中的简短示例。因此,现在TimerTask将仅counter每 3 秒增加 1,并且每次检查计数器时Thread将显示counters 值休眠 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
    }
}
于 2012-07-29T09:03:48.480 回答
5
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++;
   }

}
于 2014-05-20T12:52:19.303 回答
3

为了每三秒做一次你应该使用 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();
    }
}
于 2012-07-29T07:20:15.360 回答
2

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

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

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

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

于 2012-07-29T06:13:15.533 回答
1

Timer&TimerTask是遗产

Timer&TimerTask类现在是legacy。要在特定时间运行代码,或重复运行代码,请使用计划的执行器服务

引用TimerJavadoc 类:

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

执行器框架

在现代 Java 中,我们使用Executors 框架而不是直接寻址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 中。任何到达预定执行器服务的未捕获异常或错误都会导致静默停止进一步安排任何运行。
于 2021-03-03T08:11:46.563 回答