Reputation: 11918
Is it possible to create a separate background thread which would separately do some stuff? I've tried the following program but it doesn't work as I expect.
public class Test {
private static class UpdaterThread extends Thread {
private final int TIMEOUT = 3000;
public void run() {
while (true) {
try {
Thread.sleep(TIMEOUT);
System.out.println("3 seconds passed");
} catch (InterruptedException ex) {
}
}
}
}
/**
* @param args
* the command line arguments
*/
public static void main(String[] args) {
try {
Thread u = new UpdaterThread();
u.start();
while (true) {
System.out.println("--");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I expected that every 3 seconds "3 seconds passed" will be printed in the flow of multiple "--" strings. In fact "3 seconds passed" is never printed. Why? And how can I create a background thread which would do something independantly from the main thread?
Upvotes: 11
Views: 21837
Reputation: 5390
There are lot of answers but nobody says why his example was not working. System.out
is output stream, so after you have started write to this stream JAVA locks it and all other threads will wait while lock is applied to stream. After the stream will have unlocked another thread will be able to work with this stream.
To make your example working you should add Thread.sleep
into while
loop in the main thread.
Upvotes: 2
Reputation: 46219
I would recommend using a ScheduledExecutorService
. To run your UpdaterThread()
every 3 seconds, you can do like this:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new UpdaterThread(), 0, 3000, TimeUnit.MILLISECONDS);
You can read more here: Java Tutorials - Executor Interfaces.
Upvotes: 1
Reputation: 272307
You can use the above approach to run stuff periodically, although a TimerTask
may be simpler.
With respect to your output, I suspect your main thread isn't allowing your UpdaterThread
to run, since it's in a very tight loop. Note that this would be dependent on CPUs/cores available etc.
Have you considered sleeping in your main thread, or using Thread.yield() ? Note the provisos in that linked page:
When to use yield()?
I would say practically never. Its behaviour isn't standardly defined and there are generally better ways to perform the tasks that you might want to perform with yield(): if you're trying to use only a portion of the CPU, you can do this in a more controllable way by estimating how much CPU the thread has used in its last chunk of processing, then sleeping for some amount of time to compensate: see the sleep() method;
Note also this interesting article on handling thread interruptions.
Upvotes: 3
Reputation: 328639
It does print "3 seconds passed". Remove the System.out.println("--")
and you will see them more easily ;-)
Now you could also use a ScheduledExecutorService
, and use a Runnable
instead of a Thread
:
public class Test {
private static class Updater implements Runnable {
@Override
public void run() {
System.out.println("3 seconds passed");
}
}
public static void main(String[] args) throws InterruptedException {
Runnable r = new Updater();
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(r, 0, 3, TimeUnit.SECONDS);
Thread.sleep(10000);
service.shutdown();
}
}
Upvotes: 7
Reputation: 121971
Use java.util.TimerTask
and java.util.Timer
:
Timer t = new Timer();
t.scheduleAtFixedRate(
new TimerTask()
{
public void run()
{
System.out.println("3 seconds passed");
}
},
0, // run first occurrence immediately
3000); // run every three seconds
Upvotes: 21