The Answer by iota correctly solved your direct problem. But looking at the bigger picture, you are using obsolete classes. The modern approach with executor service and runnable is easier and simpler.
Avoid the legacy classes
The Timer and TimerTask classes were supplanted with the executor service framework in Java 5 and later.
Likewise, the terrible Date class was supplanted years ago by the modern java.time classes defined in JSR 310. Replaced specifically by java.time.Instant.
Environment class
Let's define your Environment class. This class monitors two pieces of equipment that sample the environment, and reports the current readings when asked via its report method.
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
Define your task as a Runnable object having a run method.
Using lambda syntax, that would simply be:
Runnable task = ( ) -> environment.report() ;
Or use a method reference.
Runnable task = environment :: report ;
Or, if you are not comfortable with the modern syntax, use an anonymous class.
Runnable task = new Runnable()
{
@Override
public void run ( )
{environment.report();}
};
Scheduled executor service
The ScheduledExecutorService interface repeatedly runs a task, a Runnable. You have a choice of scheduleAtFixedRate or scheduleWithFixedDelay, so read the Javadoc to decide which kind of cadence fits your needs.
Be sure to gracefully shutdown your executor service. Otherwise, its backing thread pool may run indefinitely, like a zombie ♂️. We use a try-finally to make sure the executor service is shutdown. FYI, in the future when Project Loom arrives, ExecutorService will be AutoCloseable. We will then be able to use try-with-resources syntax for simpler approach to do the shutdown.
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(); }
}
}
When run:
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
In real work, surround the innards of your Runnable with a try-catch to catch any unexpected exceptions (and maybe errors). An exception/error bubbling all the way up to the scheduled executor service causes the service to halt silently, with no further executions performed.