I start two threads with a Timer and TimerTasks
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
doSomething();
}
};
Calendar start = Calendar.getInstance();
timer.scheduleAtFixedRate(task, start.getTime(),
1000 * 60 * 60);
Now sometimes the second thread stops. Is there a possibility to observe the thread perhaps for sending a mail when this thread stops, maybe by a third thread that looks for the second thread?
You need to keep the reference to your Timer alive - if the Timer is garbage collected, the thread will stop. From the docs:
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. By default,
the task execution thread does not run
as a daemon thread, so it is capable
of keeping an application from
terminating. If a caller wants to
terminate a timer's task execution
thread rapidly, the caller should
invoke the timer's cancel method.
That may not be the problem, but it's the most likely cause. I assume if you can keep the thread alive, you don't need anything checking it?
I'd suggest adding a Thread#setDefaultUncaughtExceptionHandler to your program. You can have this log/email/etc.. While having a catch(Throwable) is better design, having an uncaught exception handler can handle any cases you miss.
Related
I have a ReentrantReadWriteLock in my application. In the run method of the timertask, I do write lock and then call a function. After that I unlock:
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
lock.writeLock().lock();
function();
lock.writeLock().unlock();
}
}, 0, 1000); // prints 1 every 1second
The thing I'm worried about is what happens if this timer is canceled and the lock is not able to unlock. Is there a way o make it so that calling .cancel will stop the timer only after the current iteration is done.
Or is there another data structure I could use that allows me to, on a separate thread, run a task/function at a certain rate and be able to stop it such that all locks are released?
The javadoc tells that calling cancel() won't interrupt a currently running task, so you are safe on this part.
However, I recommand you to use ScheduledThreadPoolExecutor instead of Timer if you can.
It's more powerful, simpler to use, and more resilient to potential exceptions thrown by scheduled tasks.
With ScheduledThreadPoolExecutor, you may cancel a particular task by calling cancel(boolean mayInterruptIfRunning) on the Future returned when scheduling the task, or cancel all scheduled tasks by terminating the scheduler (see shutDown + awaitTermination methods).
If you only need a single thread working on the tasks, you can do so.
I also strongly recommand enclosing lock acquisition and release into a try...finally block.
This will make sure that, whenever problem occurs inside the task, the lock will always be released properly.
Otherwise, as you have well observed, a problem in the task will prevent the lock from being released.
I have written a task to send a certain TCP message through a socket. I have a file with a bunch of messages and some timestamps, so I programmed the task as a TimerTask, and I scheduled it with a Timer with the first message timestamp.
When it finishes, the task run method is over, but its associated thread remains, it's not cancelled. If I try to reschedule the task with a new Time, I'm getting an exception telling me that I cannot reschedulle a schedulled or cancelled task.
I also tried cancellig it before rescheduling, but obviously, as the exception told, it remains the same problem.
I can't schedule the task with a constant perior to let it repeat itself, because each message has a time and it is not constant.
How can I reschedule the TimerTask? And by the way, is there any way of waiting for the task to end, just as in socket communications when it blocks with ready method until a message arrives?
A TimerTask is not designed to be rescheduled and it is the Timer that manages the (single) thread.
Use one Timer and many new TimerTasks:
Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially ..
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread [should] terminates gracefully (and becomes subject to garbage collection).
[From each of the schedule methods:]
Throws IllegalStateException if [the TimerTask] was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
If there are indeed many threads spawned by a single Timer, then that would be a bug which is unlikely: make sure there really is only one Timer object being used.
The last question, of how to compose individual events into a workflow, should be a separate post.
public class MyTimerTask extends TimerTask{
#Override
public void run() {
int i = 0;
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Run Me ~" + ++i);
System.out.println("Test");
}
}
Case 1 :-
TimerTask task = new MyTimerTask();
Timer timer = new Timer();
timer.schedule(task, 1000,6000); // line 1
System.out.println("End"); // here is bebug point.
My Expectation of schedule() method (as per my understanding given in javadocs where each execution is scheduled once previous task execution is completed)
that two threads should be
created after line 1.
One for timer which spawns another thread for tasks. Once first task thread dies
another will be created and son on. But at debug point , i just see one thread corresponding to Timer. Why
not thread for tasks which implement Runnable?
Case 2 :-
TimerTask task = new MyTimerTask();
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 1000,6000); // line 1
System.out.println("End"); // here is bebug point.
My Expectation of scheduleAtFixedRate() method(as per my understanding given in javadocs where each execution is scheduled relative to the scheduled
execution time of the initial execution) that around 17 threads(dont pay much attention
to 17. It can be more or less to that. But it should be greater than 2 ) should be
created after line 1.
One for timer which should spawn 16 other thread corresponding two each task. At first task sleeps
for 100 second, Timer should create another thread corresponding to next task and similarly for other task.
But at debug point , i just see one thread corresponding to Timer. Here also i can see sequential execution of task. Why not 17 threads?
UPDATE :- As per ScheduleAtFixedRate javadocs , each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up. what does that mean? To me it gives impression, if second task is due even first task is not completed, then timer will create new thread for due task. Is n't it?
Timer uses the Active Object pattern under the hood, so there is only ever a single thread being used and scheduling a new task on the timer adds that task to the thread's tasks queue.
The timer thread keeps track of all the tasks in it's queue and sleeps until the next task is scheduled. Then, it wakes up and executes the task itself by invoking task.run() directly, meaning that it does not spawn another thread to execute the code.
This also means that if you schedule two tasks to execute at the same time then, true to the Active Object pattern, they will be executed sequentially (one after another) on the same thread of control. This means the second task will execute after it's scheduled time (but probably not by much).
Now, to unequivocally answer your question, here is the scheduling logic from Timer.class that schedules the next time that the task should be run again (from lines 262-272 here):
// set when the next task should be launched
if (task.fixedRate) {
// task is scheduled at fixed rate
task.when = task.when + task.period;
} else {
// task is scheduled at fixed delay
task.when = System.currentTimeMillis()
+ task.period;
}
// insert this task into queue
insertTask(task);
task.fixedRate is set to true if you use one of the timer.scheduleAtFixedRate() methods and is set to false if you use one of the timer.schedule() methods.
task.when is the "time" (ticks) that the task was scheduled to run.
task.period is the interval you passed to the timer.schedule*() method.
So, from the code we can see that if you use a fixed rate then a repeating task will be scheduled to run relative to when it was first started. If you don't use a fixed rate, then it is scheduled to run relative to when it was last run (which will drift relative to a fixed rate, unless your task is never delayed and takes less than one tick to execute).
This also means that if a task falls behind and it is on a fixed rate, then Timer will keep rescheduling the task for immediate execution until it catches up to the total number of times it should have ran over a given period.
So if you have a task, say a ping() that you schedule to run at a fixed rate every 10ms and there is temporary blocking in the ping() method to where it takes 20ms to execute, then the Timer will call ping() again immediately after the previous call finished, and it will keep doing so until the given rate is achieved.
The javadoc for Timer says
Corresponding to each Timer object is a single background thread that
is used to execute all of the timer's tasks, sequentially.
Basically it holds a queue of tasks to which it adds when you schedule them. It uses one thread to iterate over the queue and execute the tasks.
The timer class creates one thread per instance of the timer class and this thread do all tasks scheduled Timer#schedule or Timer#scheduleAtFixRate.
So, as you ovserved, the timer creates only one thread.
A task would have came start time before the preciding task has finished, then the follwing task has waited until the preciding task has finished.
So, Timer "never" create another thread although the preciding task hasn't finished and the time the following task has to start has come.
So, I advise you that:
if you want to schedule tasks and do the tasks on time whether a preciding task has finished or not, use ScheduledThreadPoolExecutor instead of Timer.
And though if you do not want, it's prefer to use ScheduledThreadPoolExecutor than Timer because for one thing, tasks scheduled by Timer would never have done if a task would have threw RuntimeException or Error.
Schedule will not execute the missed task if the start time is in the past.
scheduleAtFixedRate will execute the missed tasks if the start time is in the past.For the missed tasks, the start time will be calculated based last task's end time. When missed tasks are executed fully, the new normal tasks' start time will be calculated based on last task's start time.
BR Sanchez
This question is a followup on this one.
Essentially what I am doing is declaring a ThreadPoolExecutor with just one thread. I am overriding the beforeExecute() method to put a sleep so that each of my tasks are executed with some delay among themselves. This is basically to give away the CPU to other threads since my thread is kind of thrashing.
So the expected behavior is:
For each new task in the ThreadPoolExecutor, it calls the before execute function before executing the task and hence it sleeps for say 20s before it executes the task.
However this is what I see:
For each new task submitted:
It executes the task
Calls the beforeExecute method
sleeps for say 20s
RE-EXECUTE the task!
The order of 1. & 2. is not the same all the time.
Here are my questions:
It is appearing that a new thread comes in after/during sleeping and goes ahead and executes my task right away while the actual thread is sleeping.
So does the ThreadPoolExecutor spawn a new thread as soon as an existing thread sleeps [thinking that the thread is terminated]??
I tried to put the keepAliveTime > sleeptime ..so that in case the above assertion is true .. it atleast waits for more than sleep time to spawn a new thread ...[hoping in the mean time the sleeping thread would be awake and the ThreadPoolExecutor would dump the idea of spawning a new thread
Even if it does spawn a new thread and execute my task right away, why would the task be re-executed after the sleeping thread wakes up !! Shouldn't the task be taken out of task Queue before that ??
Am I missing something here ? Any other way to debug this scenario ?
=> An alternative method I was thinking to do the desired task [and not solve the peoblem] was to wrap the runnable with one more runnable and sleep the outer runnable before calling the inner one.
I think what you're looking for is a ScheduledExecutorService
From what I understand of your question, scheduleAtFixedRate(...) should do the deal:
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
Creates and executes a periodic action
that becomes enabled first after the
given initial delay, and subsequently
with the given period; that is
executions will commence after
initialDelay then initialDelay+period,
then initialDelay + 2 * period, and so
on.
No, that is not how it works. The ThreadPoolExecutor knows it has a worker thread, even if that worker is RUNNABLE, WAITING, BLOCKED, or any other state.
The task is removed from the BlockingQueue long before the beforeExecute method is invoked.
You can look at the code for the API yourself and determine what it is doing. Every Java JDK installation includes a "src.zip" file which contains the entire Java Library. If yu haven't already, you can attach this source in eclipse and then while debugging in eclipse diving into a library method will show you source instead of just the class file.
Quick question about the theory of GCing. I have the following method. It runs, and exits the method. How come even after GC is run, the timer still exists and keeps "TICK"ing? I don't believe there's still a reference to timer or the timertask anymore after this method exists, so I'd expect the timer to be GCed and cause an exception. Please help me understand this concept.
Thanks,
jbu
private void startTimer()
{
Timer timer= new Timer();
TimerTask timerTask= new TimerTask()
{
#Override
public void run()
{
System.out.println("TICK");
}
};
timer.scheduleAtFixedRate(timerTask,
0,
500);
}
The Timer object actually schedules tasks to be executed in a background thread, so that background thread maintains a reference to the Timer (and the TimerTask), which prevents both from being garbage-collected.
Here is the appropriate quote from the docs:
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. By default,
the task execution thread does not run
as a daemon thread, so it is capable
of keeping an application from
terminating. If a caller wants to
terminate a timer's task execution
thread rapidly, the caller should
invoke the the timer's cancel method.
So the condition that "all outstanding tasks have completed execution" is not satisfied, and the thread never terminates, so the Timer/TimerTask is never GC'd.
Because a Timer has a background thread that continues running:
Corresponding to each Timer object is
a single background thread that is
used to execute all of the timer's
tasks, sequentially. Timer tasks
should complete quickly. If a timer
task takes excessive time to complete,
it "hogs" the timer's task execution
thread. This can, in turn, delay the
execution of subsequent tasks, which
may "bunch up" and execute in rapid
succession when (and if) the offending
task finally completes.
Since it's a background thread, it continues until the JVM exits or it's stopped.
Update: a little more on this. A "background thread" is the same thing as a daemon thread -- named by analogy with a BSD daemon process. If you see the javadocs on Thread, you'll find:
Marks this thread as either a daemon
thread or a user thread. The Java
Virtual Machine exits when the only
threads running are all daemon
threads.
When your main terminates, all the user threads stop, leaving only daemon threads. The JVM then shuts down. For a good time — if short — call Thread.currentThread().setDaemon(true); from main.
Update: Ack. I had that almost right. You have to make the timer a daemon at construction time. (Did this change, or did I just have a brain failure?)
Anyway, here's example code:
import java.util.*;
class Chatter extends TimerTask {
public void run(){
System.err.println("Timer run.");
}
}
public class TryThread {
public static void main(String[] argv){
// If argument is true, only runs a few times.
Timer t = new Timer(false);
t.schedule(new Chatter(), 1L, 1L);
return ;
}
}
The timer's not being garbage collected because it's still running -- some other object (such as the thread scheduler) still has a reference to it, which was probably created inside scheduleAtFixedRate().
How do you know the GC ran? Garbage collection in general is not a deterministic thing, and it's definitely not triggered by method scope. It's not like C++ where you leave scope of a function and destructors fire. It will get around to collecting that memory if and when the GC feels like it.