In the following code is it possible to reuse the same timer1 object again instead of timer2 for invoking timertask?
Timer timer1 = new Timer();
timer1.scheduleAtFixedRate(new TimerTask() {
int counter = 0;
#Override
public void run() {
PriorityQueueHandler.getQueueInstance().addToQueue(passengers.get(counter));
counter++;
if(counter == passengers.size()){
counter = 0;
}
}
}, DELAY, ARRIVAL_INTERVAL);
PriorityQueueHandler.getQueueInstance().print();
Timer timer2 = new Timer();
timer2.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
PriorityQueueHandler.getQueueInstance().print();
}
}, DELAY, BOOKING_INTERVAL);
You can reuse a timer instance for several tasks. Notice that a timer executes all tasks in one single thread synchronous which means that if one task is stalled this will affect the other tasks scheduled on the same timer, i.e. the other task will not be executed.
Yes, that should be fine - if you're happy with the tasks running sequentially. From the docs:
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.
It's fine to have many scheduled tasks:
Implementation note: This class scales to large numbers of concurrently scheduled tasks (thousands should present no problem). Internally, it uses a binary heap to represent its task queue, so the cost to schedule a task is O(log n), where n is the number of concurrently scheduled tasks.
Personally I'd probably use a ScheduledExecutorService to give more control over the threads created and concurrency between tasks, but that's a slightly different matter.
Related
My problem is we have to give it a fixed schedule time to make it start task. Lets say i give 10 seconds and my task has average finish time of 10-15 seconds. Thus after some time waiting threads in quque causes huge memory consumption. If i use syncronized for the method above problem will occur. If i don't use syncronized then i am wasting resources ( cpu) because i dont need to run task if not finished. So i thought a solution of recursive call of task but i believe recursive threads will add more memory problems... what should i do? Shortly i just want to be able to call a task when it is finished. Not fixed time.
public void myScheduledTask{
doJob(); ( use countdown latch to control waiting if necessary)
TimeUnit.SECONDS.sleep(x);
new Thread( new Runnable( { mySchedulTask(); } ));
or
executor.execute( a thread that call myScheduledTask() method);
}
The option that sounds like what you're trying to accomplish:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(count);
ScheduledFuture<?> future = executor.scheduleWithFixedDelay(
task,
delay,
delay,
TimeUnit.MILLISECONDS
);
This would start your task and execute it after delay milliseconds after the previous completion. Count should be the number of threads you want to use, 1 is acceptable. This also lets you stop the task using the future.
The problems with your example. a) You are sleeping on an executor thread. Dont do this let the executor handle it. If you were using a threadpool of 1 then this executor couldn't do any work while you're waiting. b) Starting a new thread is taking control from the executor... just use the executor, then you have some control over the execution.
If you really wanted to stick with the form you have.
class RecurringTask implements Runnable{
#Override
public void run(){
doJob();
executor.schedule(this, delay, TimeUnit.MILLISECONDS);
}
}
Now you will be creating Futures that you never use, so it will be harder to control the execution of the task.
Create static member in your task class - Lock.
In doJob avoid performing job if lock is already aquired :
if (lock.tryLock()) {
try {
// do the job
} finally {
lock.unlock();
}
} else {
// log the fact you skipped the job
return;
}
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
What is the most accurate way to call a function every N milliseconds?
Thread with Thread.sleep
TimerTask
Handler with postDelayed
I modified this example using Thread.sleep and it's not very accurate.
I'm developing a music app that will play sounds at a given BPM. I understand it's impossible to create an entirely accurate metronome and I don't need to - just looking to find the best way to do this.
Thanks
There are some disadvantages of using Timer
It creates only single thread to execute the tasks and if a task
takes too long to run, other tasks suffer.
It does not handle
exceptions thrown by tasks and thread just terminates, which affects
other scheduled tasks and they are never run
ScheduledThreadPoolExecutor deals properly with all these issues and it does not make sense to use Timer.. There are two methods which could be of use in your case.. scheduleAtFixedRate(...) and scheduleWithFixedDelay(..)
class MyTask implements Runnable {
#Override
public void run() {
System.out.println("Hello world");
}
}
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
long period = 100; // the period between successive executions
exec.scheduleAtFixedRate(new MyTask(), 0, period, TimeUnit.MICROSECONDS);
long delay = 100; //the delay between the termination of one execution and the commencement of the next
exec.scheduleWithFixedDelay(new MyTask(), 0, delay, TimeUnit.MICROSECONDS);
On Android you can create Thread with it's own Handler/Message Queue. It's quite accurate. When you see Handler documentation you can see, that it was designed for that.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
They are all the same precision-wise. Java timing precision is subject to the precision and accuracy of system timers and schedulers and is not guaranteed. See Thread.sleep and Object.wait API.
Using TimerTask for the loop action is the better one. Recommend
Suppose that I have the general scheduled task shown below
Timer t = new Timer();
TimerTask listenHandover = new TimerTask() {
public void run()
{
// Some methods that can possibly take more than 1 second to execute
}
};
t.schedule(listenHandover, 1000 , 1000);
As the comment says, what happens if the task takes more than 1 second to execute ? Will the currentlly running one will be restarted when the next one is scheduled ? or do the tasks have their own threads ? Hope it was clear. Thanks
If task takes more than 1 second, subsequent tasks will be queued up until offending one completes.
As per javadoc
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.
I'm interested in using ScheduledExecutorService to spawn multiple threads for tasks if task before did not yet finish. For example I need to process a file every 0.5s. First task starts processing file, after 0.5s if first thread is not finished second thread is spawned and starts processing second file and so on. This can be done with something like this:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4)
while (!executor.isShutdown()) {
executor.execute(task);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// handle
}
}
Now my question: Why I can't do it with executor.scheduleAtFixedRate?
What I get is if the first task takes longer, the second task is started as soon as first finished, but no new thread is started even if executor has pool of threads. executor.scheduleWithFixedDelay is clear - it executes tasks with same time span between them and it doesn't matter how long it takes to complete the task. So probably I misunderstood ScheduledExecutorService purpose.
Maybe I should look at another kind of executor? Or just use code which I posted here? Any thoughts?
I've solved the problem by launching a nested anonymous runnable in each scheduled execution:
final ScheduledExecutorService service = Executors.newScheduledThreadPool(POOL_SIZE);
final Runnable command = new SlowRunnable();
service.scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
service.execute(command);
}
}, 0, 1, TimeUnit.SECONDS);
With this example there will be 1 thread executing at every interval a fast instruction, so it will be surely be finished when the next interval is expired. The remaining POOL_SIZE-1 threads will be executing the SlowRunnable's run() in parallel, which may take longer time than the duration of the single interval.
Please note that while I like this solution as it minimize the code and reuse the same ScheduledExecutorService, it must be sized correctly and may not be usable in every context: if the SlowRunnable is so slow that up to POOL_SIZE jobs get executed together, there will be no threads to run the the scheduled task in time.
Also, if you set the interval at 1 TimeUnit.NANOSECONDS it will probably became too slow also the execution of the main runnable.
One of the scheduleAtFixedRate methods is what you're looking for. It starts a task in a thread from the pool at the given interval, even if previous tasks haven't finished. If you're running out of threads to do the processing, adjust the pool size constraints as detailed in the ThreadPoolExecutor docs.