I have a question about the behaviour of Timer class in Java.
This is the code: http://pastebin.com/mqcL9b1n
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.foo();
m = null;
}
public void foo() {
Timer t = new Timer();
t.schedule(new SysPrint(), 200);
}
}
class SysPrint extends TimerTask {
public void run() {
System.out.println("Yes!");
}
}
What happens is that if you run that program, it will print "Yes!" and it's not gonna do anything else (the program doesn't end).
The Java documentation 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).
As I see this thing, the "last live reference" to the Timer object is gone after the 'foo()' functions ends. And the only task scheduled was the "Yes!" task that was executed, so I guess that after the process printed "Yes!", the Timer object should end and the process should terminate.
What happened here?
Java is not exiting because your thread running the Timer is still kicking around. You have to mark that thread as being a daemon thread before Java will exit. You probably don't have access to the thread itself so unless Timer has a method to mark it so you'll have a hard time doing that. You'll need to manually stop it in a finally clause.
try {
timer = new Timer();
timer.schedule( new SysPrint(), 200 );
} finally {
timer.cancel();
}
I believe the code below should do the trick.
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.foo();
m = null;
}
public void foo() {
Timer t = new Timer();
t.schedule(new SysPrint(), 200);
}
}
class SysPrint extends TimerTask {
SysPrint(Timer timer) {
this.timer = timer;
}
public void run() {
System.out.println("Yes!");
timer.cancel();
}
private Timer timer;
}
When you create a Timer object. A TimerThread is created. And it the internal thread to run your task. You can view the method run() of TimerThread. You can see it has a while loop.
private void mainLoop() {
while (true) {....
The TimerThread not set to a daemon, so the main method execute completely, the jvm not exists.
That why your program is always running and don't stop.
Related
In my main thread I send some data to server via HttpURLConnection, then I start a timer to execute a TimerTask periodically to check the response of server. When I get the expected string I call timer.cancel(). After this, main thread resume from where the timer is started.
I imagine following simplified code with the same mechanism just for this post:
public class Test {
public static void main(String[] args) throws InterruptedException {
System.out.println("start");
Timer timer = new Timer();
TmTask timerTask = new TmTask(timer);
Thread thread = new Thread(timerTask,"thread_1");
thread.start();
thread.join();
System.out.println("end");
}
}
class TmTask extends TimerTask{
Timer t;
public TmTask(Timer t){
this.t = t;
}
#Override
public void run() {
t.schedule(new A(t), 100, 1000);
}
}
class A extends TimerTask{
private Timer t;
private int i = 0;
public A(Timer t) {
this.t = t;
}
#Override
public void run() {
System.out.println("abc" );
i++;
if (i == 3) t.cancel();
}
}
My expection is :
start
abc
abc
abc
end
But I get:
start
end
abc
abc
abc
Finally I realized that in my code there are 3 threads created but I expected 2 (main thread, and Timer thread), and the join() method works on the thread named thread_1 instead of the timer thread. But I have no idea how to improve it.
Can anyone help me? Thanks in advance.
The whole purpose of creating a new Thread is to start it separately from the main thread - to get parallel execution. You got 3 threads because the timertask creates its own thread. If you want your current (main) thread to stop and wait for result then you can just do something like:
boolean result = false;
while( ! result ) {
result=checkForResult();
Thread.sleep(1000);
}
This will pause the current thread and cause it to block. Usually for such external tasks and async calls you DO NOT want the main thread to stop execution and wait because you don't know when will you get result and it might wait indefinitely. So probably your result is the desired one? :)
I am trying to execute a task periodically. For example:
class MyTimerTask implements TimerTask
{
public void run() {
// Some actions to perform
}
Timer cleaner = new Timer(true);
cleaner.scheduleAtFixedRate(new MyTimerTask(), 0, PURGE_INTERVAL);
}
However, the run method is executing only once. But if I put the first time delay as 10 seconds, then the run method doesn't execute even once.
Example:
cleaner.scheduleAtFixedRate(new MyTimerTask(), 10, PURGE_INTERVAL);
This sounds like an issue with time units to me. Ensure that you're converting to milliseconds correctly.
The easiest way to do this is to use Java's TimeUnit.
Timer cleaner = new Timer(true);
cleaner.scheduleAtFixedRate(new MyTimerTask(),
TimeUnit.SECONDS.toMillis(10),
TimeUnit.SECONDS.toMillis(30));
It could also be caused by the Timer being started in daemon mode. If all your main method does is set up the timer and then return the timer will never execute since it's the last remaining thread and because it's a daemon thread the JVM will exit.
To fix this either make the timer thread not a daemon (i.e. pass false in the constructor) or make the main thread wait for user input before exiting.
Here's an example using both of the above:
public class TimerDemo extends TimerTask {
public void run() {
System.out.printf("Time is now %s%n", LocalTime.now());
}
public static void main(String[] args) throws IOException {
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerDemo(),
TimeUnit.SECONDS.toMillis(5),
TimeUnit.SECONDS.toMillis(10));
System.out.printf("Program started at %s%n", LocalTime.now());
System.out.println("Press enter to exit");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
// Wait for user to press enter
reader.readLine();
}
System.out.println("Bye!");
}
}
And output of running it:
Program started at 14:49:42.207
Press enter to exit
Time is now 14:49:46.800
Time is now 14:49:56.799
Time is now 14:50:06.799
Time is now 14:50:16.799
Time is now 14:50:26.799
[I pressed 'enter']
Bye!
Process finished with exit code 0
I had a hard time figuring out exactly what is your problem, so this might not be exactly what you are asking for, but this solution might fit you:
public class MyTimerTask implements Runnable {
private static final TimeUnit timeUnit = TimeUnit.SECONDS;
private final ScheduledExecutorService scheduler;
private final int period = 10;
public static void main(String[] args) {
new MyTimerTask();
}
public MyTimerTask() {
scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(this, period, period, timeUnit);
}
#Override
public void run() {
// This will run every 10 seconds
System.out.println("Ran...");
}
}
I'm coding an assignment and currently everything's working fine. I'm not going to post the whole thing but the essential classes being called and referenced.
Basically, my problem is that I have a GameTimer class to start a Timer in my Game:
public class GameTimer {
GameViewController gvc = GameFrame.gameViewController;
public static boolean isRunning = false;
public int seconds = 0;
public Timer timer = null;
public TimerTask task = null;
public GameTimer () {
timer = new Timer();
}
public void start() {
task = new TimerTask() {
#Override
public void run() {
gvc.updateTime(seconds);
seconds++;
}
};
timer.scheduleAtFixedRate(task, 1000, 1000);
System.out.println("Task was started");
isRunning = true;
}
public void stop() {
task.cancel();
timer.cancel();
timer.purge();
isRunning = false;
}
public void restart() {
stop();
start();
}
}
And basically I have different modes that extends a GameModel and references my GameTimer instance in my GameModel class :
public class GameModel {
public GameTimer game_timer = new GameTimer();
//... Rest of instances and classes
}
public class Mode1 extends GameModel {
public Mode1() {
if(!gamer_timer.isRunning)
game_timer.start();
else
game_timer.restart();
}
//.....Rest of methods
}
public class Mode2 extends GameModel {
public Mode2() {
if(!gamer_timer.isRunning)
game_timer.start();
else
game_timer.restart();
}
//.....Rest of methods
}
Basically, my game is a GUI and i have a drop-down box from which I select my modes. My game instantly loads Mode1 when it runs, but when I choose Mode2, it returns a NullPointerException on my
task.cancel();
I've read on some other posts that you have to cancel the TimerTask before the Timer, but whether I put timer cancel before the task cancel
task.cancel
timer.cancel()
it still gives me the same NullPointerException
Here's the error:
Exception in thread "AWT-EventQueue-0" Mode2
java.lang.NullPointerException
at GameTimer.stop(GameTimer.java:32) // task.cancel()
at GameTimer.restart(GameTimer.java:39)
at Mode2.<init>(Mode2.java:15)
Can you help me just figure out why is the task not cancelling.
Why is isRunning static?
Mode1 sets it to true. Mode2 is created and it should read false for isRunning but instead it reads true (class variable = only one used) so instead of calling start( ) it calls restart( ) and gets the NPE because it was never started and so can't be stopped.
I didn't clearly read your explanation line by line but what I can say by seeing your code is that,
Here inside restart() method you are calling stop() first and start() second
public void restart() {
stop();
start();
}
Inside the start() method you are initializing your task object like here
public void start() {
task = new TimerTask()
But as per your code this seems second priority of your code, stop() is called at first, But at that time task was not initialized. I suggest you to rearrange this as per your needs and initialize task anywhere you feel comfortable but be sure you initialized before using.
Thanks for your help. I found the solution. Mode1 is being initialized as I run the game
new Mode1 ();
and the same Mode2. It would initilized when I choose Mode2 in my game. However, because I'm reinitializing the same gameModel over my program, the isRunning would always be false at first because in my GameModel, you see me create a new instance of my GameTimer everytime. So basically, the state of the timer would never be set to true.
I've found the problem to my code but I have figured a solution yet so I will post the solution as soon I am done with it. Thank you for helping
I've a Java project which is main create an instance of a class (ThreadClient) that extends Thread. I would need that ThreadClient.run starts 2 timers to run periodically 2 methods of the ThreadClient class.
The examples I found in internet just show that the timer can start the run method of an instance of a classe that exteds the Thread class.
I woundln't need to create a new class, just to run 2 methods of the same class that creates the timers.
Something like C# does:
public class ThreadClient
{
private Timer _timer;
public ThreadClient() {
Start();
}
private void Start()
{
_timer = new Timer(3000); // Set up the timer for 3 seconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true; // Enable it
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
// do something
}
}
Method _timer_Elapsed belongs to the class that creates the timer.
Thanks in advance,
Samuel
That's how I finally reached my goal:
// Timer to process sales
TimerTask ttProcessSales = new TimerTask() {
#Override
public void run() {
processSales();
}
};
Timer tProcessSales = new Timer();
tProcessSales.schedule(ttProcessSales, 0, this._processTaskTimeInterval);
// Timer to process tasks
TimerTask ttProcessTask = new TimerTask() {
#Override
public void run() {
processTasks();
}
};
Timer tProcessTasks = new Timer();
tProcessTasks.schedule(ttProcessTask, 0, this._processTaskTimeInterval);
In this way I can run 2 methods of the class using timers without create new class for every method I needed to execute.
I have a class that runs for every 10 secs, but when I execute it more than once, multiple timers are started. If one timer is already running, I want the other timer calls to be ignored. I want only one timer to be running at a given point of time. Please help.
My code:
import java.util.Timer;
import java.util.TimerTask;
public class Test1 extends TimerTask{
#Override
public void run() {
System.out.println("In run method");
}
public static void main(String args[]) {
System.out.println("In main method");
Timer timer= new Timer();
timer.schedule(new Test1(), 10000,10000);
}
}
I want the 1st timer to be running always. Other timers calls should not be triggered at all.
Try with Singleton patten that allows only single instance of the class.
Sample code:
public class Test extends TimerTask {
private static Test instance = new Test();
private Test() {}
public static Test getInstance() {
return instance;
}
#Override
public void run() {
System.out.println("In run method");
}
}
Now if you try to start another Task on the same instance it will result in below exception:
java.lang.IllegalStateException: Task already scheduled or cancelled
at java.util.Timer.sched(Unknown Source)
at java.util.Timer.schedule(Unknown Source)
Why don't you try something like setting a bool true if you start a timer and only let the other Timers start if it's true or false, depends on how you set them
sth like:
boolean checkTimer = false;
//Start a Timer and set checkTimer = true
if(checkTimer == true)
{
//Start your other timers here
}
else
{
//Write message that timer is already running
}