I have the following code whose purpose is to increment a prometheus counter if periodic calls stop coming to messageReceived():
...
private static final int tenMinutes = 10 * 60 * 1000;
private Timer timer = new Timer();
private boolean newTimer = false;
...
public void messageReceived() {
timer.cancel();
timer = new Timer();
newTimer = true;
TimerTask action = new TimerTask() {
public void run() {
if (!newTimer)
counter.increment();
else
newTimer = false;
}
};
timer.schedule(action, tenMinutes, tenMinutes);
}
...
The goal is to set a timer that will only fire an action if a new event is not received. Every time messageReceived() is called before ten minutes have passed, the timer should be cancelled so it will not fire.
What I am seeing happen is pretty much exactly every ten minutes the action fires, even though messageReceived is called more than once per minute.
MessageReceived is called from a service so its not called on the same thread every time, but messageReceived is inside a singleton. I am not sure, but I would think that if multithreading was the problem, I would see many firings of "action" and not just one every 10 minutes.
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.
Hi I am working on TCP socket.
I can read data for every 1 sec. to achieve it I used TimerTask as shown in below code.
Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
finalizer = new Runnable() {
public void run() {
try {
if (navBool) {
runOnUiThread(new Runnable() {
public void run() {
new RetriveStock().execute(); // AsyncTask.
}
});
}
} catch (Exception e) {
}
}
};
handler.post(finalizer);
}
};
timer.schedule(doAsynchronousTask, 0, 1000);
For canceling this timer I used code as
timer.cancel();
timer = null;
handler.removeCallbacks(finalizer);
But it is not cancelling the timer. I do not know why.
Instead of calling timer.cancel(), you should be canceling the task that is assigned to that timer (doAsynchronousTask in your case). Since multiple TimerTasks can be assigned to one timer, calling timer.cancel() will not interfere with a currently running task.
From the Timer JavaDoc:
public void cancel()
Terminates this timer, discarding any currently scheduled tasks. Does
not interfere with a currently executing task (if it exists). Once a
timer has been terminated, its execution thread terminates gracefully,
and no more tasks may be scheduled on it.
I want to run a thread (Which does some time consuming task in background and does NOT update UI) it just downloads some files form the internet and it is independent from the UI.
I want to run this thread repeatedly after some time interval.
How can i do this, I have thread something like below:
boolean mResult =false;
void onCreate()
{
DownloadThread mDownloadThread = new DownloadThread();
mDownloadThread.start();
}
class DownloadThread extends Thread implements Runnable
{
public void run()
{
// My download code
mResult = result;
}
}
Do i need to use Handler for implementing this?
Option 1:
volatile boolean flag = true;
public void run()
{
while(flag)
{
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
}
}
Option 2:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
}
}, 0, interval);
Option 3:
volatile boolean flag = true;
public void someMethod(){
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
if(flag)
return;
else
someMethod();
}
Option 4:
final Handler handler = new Handler();
volatile boolean flag = true;
Class A implements Runnable{
public void run(){
// Do your Task
}
if(!flag)
handler.postDelayed(a, interval);
}
A a = new A();
handler.postDelayed(a);
There will be many more options. I never tried option 3 and 4. It just came to my mind and I wrote. If I were you I would use any of 1 or 2.
Prefered choice is
java.util.concurrent.ScheduledExecutorService
Newer and robust implementation, More here ScheduledExecutorService
I would use a Timer to achieve this. Try this:
void onCreate()
{
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Download your stuff
}
}, 0, 1000);
}
It starts immediately and the run-Method gets called every second.
I want to setText from within a Thread.
This is my code of the Thread:
private class GenerateThread implements Runnable {
public void run(){
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
textOut.setText("Initialising...");
});
}
}
in my main code, I use
Thread t = new Thread(new GenerateThread());
t.start();
It does not allow me to setText from within the thread.
Following some posts on internet, I have tried using a handler, but that gave me errors, I think I am double defining Runnable this way.
Handler handler (before main)
private class GenerateThread implements Runnable {
public void run(){
handler.post(new Runnable() {
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
textOut.setText("Initialising...");
});
}
}
How can I setText from within the Thread? Thanks!
besides runOnUiThread there is also View#post(Runnable) which I would prefer here because you don't need ugly looking references to the outer Activity (MyActivity.this.runOnUiThread()).
private class GenerateRunnable implements Runnable {
public void run() {
// this code is executed in a background thread.
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
textOut.post(new Runnable() {
public void run() {
// this code is executed on the UI thread.
textOut.setText("Initialising...");
}
});
}
}
#Override
protected void onResume() {
super.onResume();
new Thread(new GenerateRunnable()).start();
}
Also don't confuse Runnable and Thread. A Runnable is just an ordinary class with a run() method. It can be and often is executed on a new Thread. If you want you can also make GenerateThread a real Thread like so:
private class GenerateThread extends Thread {
#Override
public void run() {
// code here.
}
}
// start somewhere
new GenerateThread().start();
And besides using classic Thread you could also think about using AsyncTask since that is made exactly for tasks that do something long running and need to update the UI afterwards or when there is progress.
One can only update the UI from the UI thread. runOnUiThread will allow you to run an action on the UI thread the next time it executes. You can do something like:
runOnUiThread(new Runnable() {
public void run() {
textOut.setText("Initialising...");
}
});
EDIT:
private class GenerateThread implements Runnable {
public void run(){
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
// Update the UI
MyActivity.this.runOnUiThread(new Runnable() {
public void run() {
textOut.setText("Initialising...");
}
});
}
}
I have a specific function that I want to be executed after 5 seconds.
How can I do that in Java?
I found javax.swing.timer, but I can't really understand how to use it. It looks like I'm looking for something way simpler then this class provides.
Please add a simple usage example.
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
5000
);
EDIT:
javadoc says:
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection). However, this can take arbitrarily long to occur.
Something like this:
// When your program starts up
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
// then, when you want to schedule a task
Runnable task = ....
executor.schedule(task, 5, TimeUnit.SECONDS);
// and finally, when your program wants to exit
executor.shutdown();
There are various other factory methods on Executor which you can use instead, if you want more threads in the pool.
And remember, it's important to shutdown the executor when you've finished. The shutdown() method will cleanly shut down the thread pool when the last task has completed, and will block until this happens. shutdownNow() will terminate the thread pool immediately.
Example of using javax.swing.Timer
Timer timer = new Timer(3000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// Code to be executed
}
});
timer.setRepeats(false); // Only execute once
timer.start(); // Go go go!
This code will only be executed once, and the execution happens in 3000 ms (3 seconds).
As camickr mentions, you should lookup "How to Use Swing Timers" for a short introduction.
As a variation of #tangens answer: if you can't wait for the garbage collector to clean up your thread, cancel the timer at the end of your run method.
Timer t = new java.util.Timer();
t.schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
// close the thread
t.cancel();
}
},
5000
);
My code is as follows:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here, and if you have to refresh UI put this code:
runOnUiThread(new Runnable() {
public void run() {
//your code
}
});
}
},
5000
);
Your original question mentions the "Swing Timer". If in fact your question is related to SWing, then you should be using the Swing Timer and NOT the util.Timer.
Read the section from the Swing tutorial on "How to Use Timers" for more information.
you could use the Thread.Sleep() function
Thread.sleep(4000);
myfunction();
Your function will execute after 4 seconds. However this might pause the entire program...
ScheduledThreadPoolExecutor has this ability, but it's quite heavyweight.
Timer also has this ability but opens several thread even if used only once.
Here's a simple implementation with a test (signature close to Android's Handler.postDelayed()):
public class JavaUtil {
public static void postDelayed(final Runnable runnable, final long delayMillis) {
final long requested = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
// The while is just to ignore interruption.
while (true) {
try {
long leftToSleep = requested + delayMillis - System.currentTimeMillis();
if (leftToSleep > 0) {
Thread.sleep(leftToSleep);
}
break;
} catch (InterruptedException ignored) {
}
}
runnable.run();
}
}).start();
}
}
Test:
#Test
public void testRunsOnlyOnce() throws InterruptedException {
long delay = 100;
int num = 0;
final AtomicInteger numAtomic = new AtomicInteger(num);
JavaUtil.postDelayed(new Runnable() {
#Override
public void run() {
numAtomic.incrementAndGet();
}
}, delay);
Assert.assertEquals(num, numAtomic.get());
Thread.sleep(delay + 10);
Assert.assertEquals(num + 1, numAtomic.get());
Thread.sleep(delay * 2);
Assert.assertEquals(num + 1, numAtomic.get());
}
All other unswers require to run your code inside a new thread.
In some simple use cases you may just want to wait a bit and continue execution within the same thread/flow.
Code below demonstrates that technique. Keep in mind this is similar to what java.util.Timer does under the hood but more lightweight.
import java.util.concurrent.TimeUnit;
public class DelaySample {
public static void main(String[] args) {
DelayUtil d = new DelayUtil();
System.out.println("started:"+ new Date());
d.delay(500);
System.out.println("half second after:"+ new Date());
d.delay(1, TimeUnit.MINUTES);
System.out.println("1 minute after:"+ new Date());
}
}
DelayUtil Implementation
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class DelayUtil {
/**
* Delays the current thread execution.
* The thread loses ownership of any monitors.
* Quits immediately if the thread is interrupted
*
* #param duration the time duration in milliseconds
*/
public void delay(final long durationInMillis) {
delay(durationInMillis, TimeUnit.MILLISECONDS);
}
/**
* #param duration the time duration in the given {#code sourceUnit}
* #param unit
*/
public void delay(final long duration, final TimeUnit unit) {
long currentTime = System.currentTimeMillis();
long deadline = currentTime+unit.toMillis(duration);
ReentrantLock lock = new ReentrantLock();
Condition waitCondition = lock.newCondition();
while ((deadline-currentTime)>0) {
try {
lock.lockInterruptibly();
waitCondition.await(deadline-currentTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} finally {
lock.unlock();
}
currentTime = System.currentTimeMillis();
}
}
}
public static Timer t;
public synchronized void startPollingTimer() {
if (t == null) {
TimerTask task = new TimerTask() {
#Override
public void run() {
//Do your work
}
};
t = new Timer();
t.scheduleAtFixedRate(task, 0, 1000);
}
}
I think in this case :
import javax.swing.*;
import java.awt.event.ActionListener;
is the best. When the Question is prevent Ui stack or a progress not visible before a heavy work or network call. We can use the following methods (from my experience) :
Run a method after one Second :
public static void startMethodAfterOneSeconds(Runnable runnable) {
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}
});
timer.setRepeats(false); // Only execute once
timer.start();
}
Run a method after n second once, Non repeating :
public static void startMethodAfterNMilliseconds(Runnable runnable, int milliSeconds) {
Timer timer = new Timer(milliSeconds, new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}
});
timer.setRepeats(false); // Only execute once
timer.start();
}
Run a method after n seconds, and repeat :
public static void repeatMethodAfterNMilliseconds(Runnable runnable, int milliSeconds) {
Timer timer = new Timer(milliSeconds, new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
runnable.run();
}
});
timer.setRepeats(true); // Only execute once
timer.start();
}
And the Usage :
startMethodAfterNMilliseconds(new Runnable() {
#Override
public void run() {
// myMethod(); // Your method goes here.
}
}, 1000);
Perhaps the most transparent way is to use the postDelayed function of the Handler class the following way:
new Handler().postDelayed(this::function, 1000);
or you can implement the function inside, for example:
new Handler().postDelayed(() -> System.out.println("A second later"), 1000);
Where the first argument is the function, the second argument is the delay time in milliseconds.
In the first example, the name of the called function is "function".