I need to execute an action after a specific amount of time (for example 30 minutes after the app started up, if the app is still up).
What are my options and will it necessary means there's going to be one thread "lost" waiting for the 30 minutes to pass by?
Ideally, at program startup, I'd like to do something like the following (simplified on purpose) and then don't have to think about it anymore:
doIfStillUp( 30, new Runnable() {
....
});
So how should I go about implementing doIfStillUp(...)?
Should I use a TimerTask? The Executor framework?
Most importantly (it's for understanding purpose): does this mean there's going to be one thread lost idling for basically nothing during 30 minutes?
If there's going to be one thread "doing nothing", is this an issue? What if there are 10 000 threads (I'm being facetious here) "doing nothing"?
Note that I'm trying to understand the "big picture", not to solve a particular problem.
The Executor framework is a reasonable choice.
There's a schedule method that just takes a runnable and a delay time.
schedule(Runnable command,
long delay,
TimeUnit unit)
That's pretty straightforward. There won't necessarily be a thread blocked waiting on your task. You could use a ScheduledThreadPoolExecutor, as linked above that keeps X threads ready to run scheduled tasks.
You can imagine a data structure that holds the time at which a task should be run. A single thread can watch or set up these delays and can potentially watch thousands of them in a single thread. When the first time expires it'll run the task. Potentially using its own thread, potentially using 1 of X in the thread pool. When a new task is added or an existing task is finished it'll wait for the earliest time to arrive and then start the whole process again.
You should use a Timer. Its javadoc answers all your questions.
One thread is used for every timer, but the timer executes several tasks, sequentially. The timer tasks should be very short. If they aren't, consider using several timers.
Of course, the timer thread will be idle if it doesn't have any task to execute. An idle thread doesn't consume anything (or nearly anything), so I wouldn't worry about it. Anyway, you don't have many choices. 10000 threads doing nothing would of course be an issue, but that would mean that you instantiated one timer per task, which is wrong.
You can schedule task on java.util.Timer. For all timer tasks single timer thread will be created by java.util.Timer.
The builtin java timer is the straight away solution: http://download.oracle.com/javase/1,5.0/docs/api/java/util/Timer.html#schedule(java.util.TimerTask, long)
Related
I was reading ScheduledThreadPoolExecutor JavaDoc and came across the following thing:
Delayed tasks execute no sooner than they are enabled, but without any
real-time guarantees about when, after they are enabled, they will
commence. Tasks scheduled for exactly the same execution time are
enabled in first-in-first-out (FIFO) order of submission.
So, if I write something like this:
ScheduledExecutorService ses = Executors.newScheduledThreadPool(4); //uses ScheduledThreadPoolExecutor internally
Callable<Integer> c;
//initialize c
ses.schedule(c, 10, TimeUnit.SECONDS);
there's no any guarantees that the execution of the callable will start in 10 seconds after the scheduling? As far as I got, the specification allows it to execute even in hour after scheduleing (without any real-time guarantees, as stated in the documentation).
How does it work in practice? Should I excepct some really long delay?
Your understanding is correct. The Executor is not claiming to be a real-time system with any sort of timing guarantees. The only thing it will guarantee is that it doesn't run tasks too early.
In practice, the timing of well-tuned Executors are very accurate. Typically they start within 10ms after the scheduled time from my experience. The only time you will see scheduling get pushed back very far is if your Executor is lacking the appropriate resources to run it's workload. So this is more of a tuning issue.
Realistically, if you give your Executor enough resources to work with, the timing will be quite accurate.
Some things that you don't want to do with an Executor is use the scheduling as part of a rate-based calculation. For example, if you schedule a task to run every 1 second and you use that to compute <somemetric> per second without factoring in what time the task is actually running at.
Another thing to be mindful of is the cost of context switching. If you schedule multiple tasks to run every 1ms, the Executor will not be able to keep up with running your task and context switching everyone 1ms.
I am using SchedulerExecuterService to execute a task after specified delay and at given intervals.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(taskThread,60 ,120 ,TimeUnit.SECONDS);
What happening is first time taskThread is not starting after delay of 60 sec, it is started after delay of more than 60 secs. Whereas the next executions started at correct intervals of 120 secs(not exactly 120 secs but there is a very minute delay which can be ignored).
My query is why the first execution is delayed for more than 60 secs? Since the task is executed by a thread, Does the start up time depends on the thread priority?
How can I make it run at exact delay of 60 secs? What about Quartz library? Will this library solve my purpose(run the job at specific time without any delay)?
Thanks in advance.
Startup of a job depends on the scheduled time and the amount of threads available - if there are none available, it can be delayed. However, further executions will start at a scheduled time (delay + n * period) - which is takes place in your case.
Start will happen approximately at a scheduled time, I doubt there are real-time guarantees for this, it depends on the underlying OS. You could try changing a thread priority for a thread in this thread pool. This could help, but it won't give you a guarantee that it would work out in different environment.
You could also make sure you run a single task for a fixed thread pool of a single thread you use. Or try increasing the thread amount.
T.b.h. the delay you are seeing is unlikely to be ScheduledExecutorService's fault. Starting a thread won't take a second unless your machine is ridiculously overloaded, and I think the thread will get initialised up-front anyways if you use a fixed size thread pool.
I'm guessing it's the initialisation of your own tasks. I don't know what you are doing in your task, but getting the resource ready (starting DB connection pools) etc. can amount to significant time.
If you want you can test with a trivial task (like writing "hello" on the console) to see. And then you can measure each part of your task to see what's taking long. Once you have that you can think of ways to "warm" your system to prevent the delay.
I have code that relies on a Timer staying alive and managing TimerTask. Usually TimersTasks will come and go and there will always be at least one TimerTask to keep the Timer alive, but every now and then all the TimerTasks will die and the Timer will die with it.
How would I keep Timer alive? Should I have one TimerTask in it at scheduled to fire at a far away date? That's what I'm leaning towards, but I want to hear what more experienced programer's ideas would be.
*It would also be nice if I could terminate all TimerTaks except for this one 'permanent' TimerTask.
Sorry if none of this makes much sense, or if I'm thinking of Timers and TimerTasks all wrong. I'm brand new to Java and all programming.
This sounds backwards. The Timer is the thing that manages the tasks. The TimerTask is the thing that is getting managed. You create a timer, you tell it to schedule the timertask, which can be singular or continuous (e.g. you can set the task to run every hour for as long as your JVM is running). It will run until it has no more tasks.
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).
I am trying to Tune a thread which does the following:
A thread pool with just 1 thread [CorePoolSize =0, maxPoolSize = 1]
The Queue used is a ArrayBlockingQueue
Quesize = 20
BackGround:
The thread tries to read a request and perform an operation on it.
HOWEVER, eventually the requests have increased so much that the thread is always busy and consume 1 CPU which makes it a resource hog.
What I want to do it , instead sample the requests at intervals and process them . Other requests can be safely ignored.
What I would have to do is put a sleep in "operation" function so that for each task the thread sleeps for sometime and releases the CPU.
Quesiton:
However , I was wondering if there is a way to use a queue which basically itself sleeps for sometime before it reads the next element. This would be ideal since sleeping a task in the middle of execution and keeping the execution incomplete just doesn't sound the best to me.
Please let me know if you have any other suggestions as well for the tasks
Thanks.
Edit:
I have added a follow-up question here
corrected the maxpool size to be 1 [written in a haste] .. thanks tim for pointing it out.
No, you can't make the thread sleep while it's in the pool. If there's a task in the queue, it will be executed.
Pausing within a queued task is the only way to force the thread to be idle in spite of queued tasks. Now, the "sleep" doesn't have to be in the same task as the "work"—you could queue a separate rest task after each real task, which might make for a cleaner implementation. More importantly, if the work is a Callable that returns a result, separating into two tasks will allow you to obtain the result as soon as possible.
As a refinement, rather than sleeping for a fixed interval between every task, you could "throttle" execution to a specified rate. This would allow you to avoid waiting unnecessarily between tasks, yet avoid executing too many tasks within a specified time interval. You can read another answer of mine for a simple way to implement this with a DelayQueue.
You could subclass ThreadPool and override beforeExecute to sleep for some time:
#Overrides
protected void beforeExecute(Thread t,
Runnable r){
try{
Thread.sleep( millis); // will sleep the correct thread, see JavaDoc
}
catch (InterruptedException e){}
}
But see AngerClown's comment about artificially slowing down the queue probably not being a good idea.
This might not work for you, but you could try setting the executor's thread priority to low.
Essentially, create the ThreadPoolExecutor with a custom ThreadFactory. Have the ThreadFactory.newThread() method return Threads with a priority of Thread.MIN_PRIORITY. This will cause the executor service you use to only be scheduled if there is an available core to run it.
The implication: On a system that strictly uses time slicing, you will only be given a time slice to execute if there is no other Thread in the entire program with a greater priority asking to be scheduled. Depending on how busy your application really is, you might get scheduled every once in awhile, or you might not be scheduled at all.
The reason the thread is consuming 100% CPU is because it is given more work than it can process. Adding a delay between tasks is not going to fix this problem. It is just make things worse.
Instead you should look at WHY your tasks are consuming so much CPU e.g. with a profiler and change them so that consume less CPU until you find that your thread can keep up and it no longer consumes 100% cpu.
I'm using Timer as an process interrupt mechanism. The flow of logic is as follows:
T0: create new timer at T0 and schedule a new timer task to execute at T2 (1 second task delay, task is very simple - sets a flag variable)
T1: in the main calling thread, sleep for 5 seconds
T2: in the timer thread, task executes
T5: sleep finishes
T6: cancel timer and any scheduled tasks
The code works perfectly on my Windows and Ubuntu dev environment. But when I run the same code on my SLES 10 build server, logging indicates this execution order:
T0: timer and timer tasks are created to execute at T2
T1: main thread sleeps for 5 seconds
T5: main thread wakes up
T6: timer cancels
T7: task executes
Could anyone offer an explanation as to why this occurs? Thanks very much.
Hm. I'm surprised that you see that much difference (in seconds?), but I guess it is possible that you see different order of execution from machine to machine, jvm to jvm etc. Especially, when the JIT is compiling your code for the first time, I tend to see delay (compared to subsequent execution of same code) in the order of 100-300ms in my code for example, so maybe it's more dramatic in your code?
Not sure what you mean with "process interrupt mechanism". Do you mean that the timer task interrupts some thread?
Anyways, what I can suggest now is to use System.nanoTime() instead. (Although I don't think it will explain anything, Use of System.currentTimeMillis() is discouraged in serious measurements). Addition of -server to your JAVA_OPTS is generally advised so that you see the behavior when the code is optimized by JIT. It is also highly advisable to run your code multiple times and take statistics.
If I were you, I'll do these small things first, then debug using synchronizers like CyclicBarrier, CountdownLatch and see where exactly the delay is coming.
What are the "background noise" (degree of activity) in the SLES? Maybe the OS is very very busy or something?
What is the task's nature? Is it anything network/IO related?
It turned out it was a timestamp issue. Using new Date().getTime instead of System.currentTimeMillis yielded the expected order of execution timestamps.
Thanks for all the good ideas.
You should consider firing an event when the tasks are complete. That ensures execution order.