我想每 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());
答案 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 的现代方法更容易、更简单。
Timer
和 TimerTask
类在 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