如何每 10 秒执行一次?

时间:2021-01-03 18:00:19

标签: java

我想每 10 秒执行一段代码。我在这个论坛上找到了一个例子,但我的实现有一些问题。

package robomow;

import robomow.SI7021;
import robomow.SGP30;
import com.pi4j.io.i2c.I2CFactory;
import java.io.IOException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Environment {
  long delay = 10000;
  LoopTask task = new LoopTask();
  Timer timer = new Timer("TaskName");

  public void start() {
    timer.cancel();
    timer = new Timer("Environment");
    SI7021 si7021 = new SI7021();
    SGP30 sgp30 = new SGP30();
    Date executionDate = new Date();
    timer.scheduleAtFixedRate(task, executionDate, delay);
  }

  private class LoopTask extends TimerTask {
    public void run() {
      System.out.printf("Humidity = %.0f  Temperature = %.2f \n", si7021.GetHumidity(), si7021.GetTemperature());
      System.out.printf("eCO2 = %d ppm TVOC = %d \n", sgp30.getECO2(), sgp30.getTVOC());
    }
  }

  public static void main(String[] args) throws InterruptedException,
  IOException,
  I2CFactory.UnsupportedBusNumberException {

    Environment EnvironmentTask = new Environment();
    SI7021 si7021 = new SI7021();
    SGP30 sgp30 = new SGP30();

    EnvironmentTask.start();

  }
}

我收到此错误,指向 si7021

Environment.java:28: error: cannot find symbol
System.out.printf("Humidity = %.0f  Temperature = %.2f \n", si7021.GetHumidity(), si7021.GetTemperature());

3 个答案:

答案 0 :(得分:3)

您声明的变量不能在 TimerTask 内部访问;你应该考虑把它们移到班级里。

    private class LoopTask extends TimerTask {
            SI7021 si7021;
            SGP30 sgp30;
            public LoopTask() {
                try {
                 si7021 = new SI7021();
                 sgp30 = new SGP30();
                } catch(Exception e){
                     //handle exception
                }
            }
            public void run() {
                    System.out.printf("Humidity = %.0f  Temperature = %.2f \n", si7021.GetHumidity(), si7021.GetTemperature());
                    System.out.printf("eCO2 = %d ppm TVOC = %d \n", sgp30.getECO2(), sgp30.getTVOC());
            }
    }

答案 1 :(得分:0)

Answer by iota 正确地解决了您的直接问题。但是从更大的角度来看,您正在使用过时的类。带有 executor service 和 runnable 的现代方法更容易、更简单。

避免遗留类

TimerTimerTask 类在 Java 5 及更高版本中被执行程序服务框架取代。

同样,可怕的 Date 类在多年前被 JSR 310 中定义的现代 java.time 类取代。专门替换为 java.time.Instant

Environment

让我们定义您的 Environment 类。此类监控两个对环境进行采样的设备,并在通过其 report 方法询问时报告当前读数。

package work.basil.example;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.*;

public class Environment
{
    private SI7021 si7021 = new Environment.SI7021();
    private SGP30 sgp30 = new Environment.SGP30();

    public void report ( )
    {
        System.out.println( "------------|  Environment Report at " + Instant.now().truncatedTo( ChronoUnit.SECONDS ) + "  |------------------------" );
        System.out.printf( "Humidity = %.0f  Temperature = %.2f \n" , si7021.getHumidity() , si7021.getTemperature() );
        System.out.printf( "eCO2 = %d ppm TVOC = %d \n" , sgp30.getECO2() , sgp30.getTVOC() );
    }

    class SI7021
    {
        public float getHumidity ( )
        {
            return ThreadLocalRandom.current().nextFloat() * 100;
        }

        public float getTemperature ( )
        {
            return ThreadLocalRandom.current().nextFloat() * 100;
        }
    }

    class SGP30
    {
        public int getECO2 ( )
        {
            return ThreadLocalRandom.current().nextInt( 1 , 100 );
        }

        public int getTVOC ( )
        {
            return ThreadLocalRandom.current().nextInt( 1 , 100 );
        }
    }
}

Runnable

将您的任务定义为具有 run 方法的 Runnable 对象。

使用 lambda 语法,就是:

Runnable task = ( ) -> environment.report() ;

或者使用方法引用。

Runnable task = environment :: report ;

或者,如果您对现代语法不满意,请使用匿名类。

Runnable task = new Runnable()
{
    @Override
    public void run ( )
    {environment.report();}
};

预定的执行者服务

ScheduledExecutorService 接口重复运行一个任务,一个 Runnable。您可以选择 scheduleAtFixedRate​scheduleWithFixedDelay,因此请阅读 Javadoc 以确定哪种节奏适合您的需要。

请务必正常关闭您的执行程序服务。否则,它的后台线程池可能会无限运行,就像僵尸?‍♂️。我们使用 try-finally 来确保执行程序服务已关闭。仅供参考,将来当 Project Loom 到达时,ExecutorService 将是 AutoCloseable。然后,我们将能够使用 try-with-resources 语法来实现更简单的关闭方法。

    public static void main ( String[] args )
    {
        System.out.println( "INFO - Starting the scheduled executor service generating Environment reports. " + Instant.now() );
        ScheduledExecutorService scheduledExecutorService = null;
        try
        {
            Environment environment = new Environment();
            scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
            Runnable task = environment :: report ;
            scheduledExecutorService.scheduleAtFixedRate(
                    task ,                                    // Implements `Runnable`.
                    0 ,                                       // Initial delay.
                    Duration.ofSeconds( 10 ).toSeconds() ,    // Period
                    TimeUnit.SECONDS )                        // Unit of time for both delay and period.
            ;
            // … do other stuff
            try { Thread.sleep( Duration.ofMinutes( 1 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }  // Give our demo a chance to run a while.
            System.out.println( "INFO - Will shutdown the scheduled executor service generating Environment reports. " + Instant.now() );
        }
        finally
        {
            if ( Objects.nonNull( scheduledExecutorService ) ) { scheduledExecutorService.shutdown(); }
        }
    }

运行时:

INFO - Starting the scheduled executor service generating Environment reports. 2021-01-04T07:46:54.494330Z
------------|  Environment Report at 2021-01-04T07:46:54Z  |------------------------
Humidity = 95  Temperature = 40.71 
eCO2 = 99 ppm TVOC = 1 
------------|  Environment Report at 2021-01-04T07:47:04Z  |------------------------
Humidity = 72  Temperature = 92.15 
eCO2 = 25 ppm TVOC = 42 
------------|  Environment Report at 2021-01-04T07:47:14Z  |------------------------
Humidity = 52  Temperature = 94.01 
eCO2 = 85 ppm TVOC = 89 
------------|  Environment Report at 2021-01-04T07:47:24Z  |------------------------
Humidity = 80  Temperature = 1.60 
eCO2 = 10 ppm TVOC = 78 
------------|  Environment Report at 2021-01-04T07:47:34Z  |------------------------
Humidity = 64  Temperature = 44.97 
eCO2 = 50 ppm TVOC = 40 
------------|  Environment Report at 2021-01-04T07:47:44Z  |------------------------
Humidity = 1  Temperature = 31.63 
eCO2 = 20 ppm TVOC = 69 
------------|  Environment Report at 2021-01-04T07:47:54Z  |------------------------
Humidity = 30  Temperature = 26.88 
eCO2 = 2 ppm TVOC = 86 
INFO - Will shutdown the scheduled executor service generating Environment reports. 2021-01-04T07:47:54.516543Z

在实际工作中,用 try-catch 包围 Runnable 的内部以捕获任何意外异常(可能还有错误)。一直冒泡到预定执行程序服务的异常/错误会导致服务静默停止,不再执行进一步的执行。

答案 2 :(得分:-1)

您需要一个类来扩展 TimerTask 并覆盖 public void run() 方法,该方法将在您每次将该类的实例传递给 timer.schedule() 方法时执行。

class Hello extends TimerTask { 
 public void run() { 
 System.out.println("Hello World!"); 
 }  
}  
// And From your main() method or any other method 
 Timer timer = new Timer(); 
 timer.schedule(new Hello(), 0, 100000);//10 Min