How to Set a Timer in Java

How to set a Timer in Java?

So the first part of the answer is how to do what the subject asks as this was how I initially interpreted it and a few people seemed to find helpful. The question was since clarified and I've extended the answer to address that.

Setting a timer

First you need to create a Timer (I'm using the java.util version here):

import java.util.Timer;

..

Timer timer = new Timer();

To run the task once you would do:

timer.schedule(new TimerTask() {
@Override
public void run() {
// Your database code here
}
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

To have the task repeat after the duration you would do:

timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// Your database code here
}
}, 2*60*1000, 2*60*1000);

// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);

Making a task timeout

To specifically do what the clarified question asks, that is attempting to perform a task for a given period of time, you could do the following:

ExecutorService service = Executors.newSingleThreadExecutor();

try {
Runnable r = new Runnable() {
@Override
public void run() {
// Database task
}
};

Future<?> f = service.submit(r);

f.get(2, TimeUnit.MINUTES); // attempt the task for two minutes
}
catch (final InterruptedException e) {
// The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
// Took too long!
}
catch (final ExecutionException e) {
// An exception from within the Runnable task
}
finally {
service.shutdown();
}

This will execute normally with exceptions if the task completes within 2 minutes. If it runs longer than that, the TimeoutException will be throw.

One issue is that although you'll get a TimeoutException after the two minutes, the task will actually continue to run, although presumably a database or network connection will eventually time out and throw an exception in the thread. But be aware it could consume resources until that happens.

How to make count down timer in Java?

You maybe do like this:

package com.example;

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

public class MyTimer {

public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new App(), 0, 1000);
}
}

class App extends TimerTask {

int countdown = 100;

public void run() {
countdown = countdown - 1;
System.out.println(countdown);
//label.setText(countdown +"second's left");
}

}

// Result:
//99
//98
//97
//96
//95
//94

It just works. Change System.out.println(countdown); by label.setText(countdown +"second's left"); as what you want.

Reference

http://docs.oracle.com/javase/8/docs/api/index.html?java/util/TimerTask.html

http://docs.oracle.com/javase/8/docs/api/index.html?java/util/Timer.html

How to make a countdown CountDown Timer in java ( stopwatch Java )

package com.test;

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

public class StopWatch
{
public static int interval;

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Input seconds => : ");
interval = input.nextInt();
int delay = 1000;
int period = 1000;
final Timer time = new Timer();
System.out.println(interval);
time.scheduleAtFixedRate(new TimerTask() {

public void run() {
if (interval == 0) {
System.out.println("work finished");
time.cancel();
time.purge();
} else {
System.out.println(setInterval());
}
}
}, delay, period);
}

private static int setInterval() {

return --interval;
}

}

How to use Java.Util.Timer

Don't use this while loop:

    task = new TimerTask() {
@Override
public void run() {
while (seconds < 100) {
System.out.println("Seconds = " + seconds);
seconds++;
}
}
};

The while loop will run immediately as there's no delay inside of it. Instead you want to Timer itself to be your loop, meaning there's no need for this loop.

Instead use an if block to check if the count is < some max number and if so, print it out and increment the count.

    task = new TimerTask() {
private final int MAX_SECONDS = 100;

@Override
public void run() {
if (seconds < MAX_SECONDS) {
System.out.println("Seconds = " + seconds);
seconds++;
} else {
// stop the timer
cancel();
}
}
};

Java Timer/TimerTask - fire event if message not received

I think you do have a multi-threading problem, just like SnowmanXL said. Here is a simple MCVE reproducing the problem:

import java.text.SimpleDateFormat;
import java.util.*;

class MiscellaneousMonitor {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");

private boolean isRunning;
private Counter counter;
private static final int tenMinutes = /*10 * 60 **/ 1000;
private Timer timer = new Timer();
private boolean newTimer = false;

static class Counter {
private int count = 0;

public /*synchronized*/ void increment() {
count++;
}
}

public /*synchronized*/ void start() {
counter = new Counter();
isRunning = true;
}

public /*synchronized*/ void messageReceived() {
timer.cancel();
timer = new Timer();
newTimer = true;
TimerTask action = new TimerTask() {
public void run() {
System.out.println(dateFormat.format(new Date()) + " Timer task running: " + this);
if (!newTimer)
counter.increment();
else
newTimer = false;
}
};
timer.schedule(action, tenMinutes, tenMinutes);
}

public /*synchronized*/ void stop() {
timer.cancel();
isRunning = false;
}

public /*synchronized*/ boolean isRunning() {
return isRunning;
}

public static void main(String[] args) throws InterruptedException {
MiscellaneousMonitor monitor = new MiscellaneousMonitor();
monitor.start();
Queue<Thread> threads = new LinkedList<>();
for (int t = 0; t < 10; t++) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try { Thread.sleep(150); } catch (InterruptedException e) { e.printStackTrace(); }
monitor.messageReceived();
}
try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); }
});
thread.start();
threads.add(thread);
}
while (!threads.isEmpty()) {
threads.poll().join();
}
monitor.stop();
}
}

The console log will look something like this:

Exception in thread "Thread-4" java.lang.IllegalStateException: Timer already cancelled.
at java.base/java.util.Timer.sched(Timer.java:398)
at java.base/java.util.Timer.schedule(Timer.java:249)
at MiscellaneousMonitor.messageReceived(scratch_3.java:39)
at MiscellaneousMonitor.lambda$main$0(scratch_3.java:59)
at java.base/java.lang.Thread.run(Thread.java:832)
09:25:58.147 Timer task running: MiscellaneousMonitor$1@1ce7fd7d
09:25:58.142 Timer task running: MiscellaneousMonitor$1@7ba42a49
09:25:58.147 Timer task running: MiscellaneousMonitor$1@493cb0eb
09:25:58.147 Timer task running: MiscellaneousMonitor$1@6f9a3afe
09:25:58.148 Timer task running: MiscellaneousMonitor$1@1d86f308
Exception in thread "Thread-9" java.lang.IllegalStateException: Timer already cancelled.
at java.base/java.util.Timer.sched(Timer.java:398)
at java.base/java.util.Timer.schedule(Timer.java:249)
at MiscellaneousMonitor.messageReceived(scratch_3.java:39)
at MiscellaneousMonitor.lambda$main$0(scratch_3.java:59)
at java.base/java.lang.Thread.run(Thread.java:832)
09:25:58.445 Timer task running: MiscellaneousMonitor$1@53c65632
09:25:58.445 Timer task running: MiscellaneousMonitor$1@6ce24daa
09:25:58.445 Timer task running: MiscellaneousMonitor$1@784b861f
09:25:58.447 Timer task running: MiscellaneousMonitor$1@783528c9
09:25:58.447 Timer task running: MiscellaneousMonitor$1@2cc4944f
09:25:58.597 Timer task running: MiscellaneousMonitor$1@711e91d9
09:25:58.597 Timer task running: MiscellaneousMonitor$1@19ddcb88
09:25:58.597 Timer task running: MiscellaneousMonitor$1@5fbdc1a8
(...)

Sometimes you see the execeptions, sometimes not, depending on the timing when you run the program. But even if you do not see any exceptions, multiple timer tasks - MiscellaneousMonitor$1 is the internal name of the anonymous TimerTask instance - will log forever and never be cancelled, which is why the program continues to run forever until you kill it, despite you calling join() on all running tasks. But there are still rogue TimerTasks.

Now if you uncomment all synchronized keywords where I put them in the code, your console log will change to the expected

09:31:44.880 Timer task running: MiscellaneousMonitor$1@4f963263

and the program will terminate.

P.S.: You maybe could synchronise on smaller sections of code instead of on whole methods, I did not analyse that. I just showed you the basic problem of thread unsafety with your singleton which is accessed by multiple other threads, like you said.



Related Topics



Leave a reply



Submit