I'm having a little problem understanding how ScheduledThreadPoolExecutor works (I'm using SCA so don't bother with the annotations inside the code). That's part of the code from my Scheduler class:
#AllowsPassByReference
public ScheduledFuture<?> schedule(Task task)
{
future=scheduler.scheduleAtFixedRate(task.getRunnableContent(), task.getDelay(), task.getPeriod(), TimeUnit.MILLISECONDS);
return future;
}
#AllowsPassByReference
public void deschedule(Task task)
{
scheduler.remove(task.getRunnableContent());
}
And that's part of the code from my Task class:
public void scheduleTask()
{
if(!running)
{
future=scheduler.schedule(this);
running=true;
}
}
public void descheduleTask()
{
if(running)
{
future.cancel(mayInterruptIfRunning);
scheduler.deschedule(this);
running=false;
}
}
Now here's the big deal! Everywhere I looked people used cancel on ScheduledFutures and then used shutdown method on the scheduler, but I don't want to stop the scheduler. Let me explain a little better: in this application periodic tasks must be scheduled, stopped and re-scheduled individually at any time, so I need a way to interrupt a single task once it started running without having shutdown the whole scheduler service. I hope you can understand what I'm trying to do, any advice? Thanks :)
When we cancel a periodic task, this task subsequent scheduling will be cancelled, but the scheduler itself will be running and can be used for scheduling another task.
If we call Future.cancel when the task is running then
a) Future.cancel(false) will not affect the running task
b) Future.cancel(true) will call Threed.interrupt on the task's thread, but whether the running task will stop or not depends on the task implementation. For instance the task may catch InterruptedException (if any) and continue working.
Related
I'm looking for a way to schedule a task after some time, but i need to be able to delay the task if something happen.
For example
myMethod() {
some code...
new Timer().schedule(new TimerTask(){
#Override
public void run(){
LOGGER.info("close connexion");
}
},1000);
}
I need to reschedule the task in "run" if i come again in myMethod().
How to do?
Solution #1
Please see at ScheduledExecutorService that is available from java 1.5 It gives your method scheduleWithFixedDelay - so it re-schedules your task only after accomplishment. Another way to re-schedule task (with schedule method) right at the end of your method
Solution #2 - near the same signature of methods exists in the Spring TaskScheduler, but you can do it with help of annotated method of services.
I have a ScheduledThreadPoolExecutor which has one thread and runs for every 30 seconds.
Now, if the current executing thread throws some exception, then I need to make sure that the next thread do not run and the the ScheduledThreadPoolExecutor is down.
How do I achieve this?
Catch the exception call shutdown/shutdownNow API in ExecutorService
shutdown()
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.
shutdownNow()
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
Refer to these post for more details with working code.
How to forcefully shutdown java ExecutorService
As a clean way, you can simply use a static accessed class to set/check the execution availability.
import java.util.concurrent.atomic.AtomicBoolean;
class ThreadManager
{
private static AtomicBoolean shouldStop = new AtomicBoolean(false);
public static void setExceptionThrown(boolean val)
{
shouldStop.set(val);
}
public boolean shouldExecuteTask()
{
return !shouldStop.get();
}
}
And a custom runnable implementation that allows you to check for the possibility to execute the task
abstract class ModdedRunnable implements Runnable
{
#Override
public void run()
{
if(ThreadManager.shouldExecuteTask())
{
try
{
runImpl();
}
catch(Exception t)
{
ThreadManager.setExceptionThrown(true);
}
}
}
public abstract void runImpl() throws Exception;
}
I have a TimerTask that gets started as the first thing in my run() method of my Runnable class. I want to make sure that it gets stopped when the runnable is shutdown.
The runnable is started via an ExecutorService. I don't see a way to get a hook back to the runnable from the ExecutorService when shutdown() is called.
How can I make sure that the TimerTask is stopped?
Thanks
use ExecuterService.submit() to get back Future object once the task is completed.
ExecutorService.Submit()
The method call TimerTask.cancel() should do the desired.
Your Runnable.run method could be designed like this:
public void run() {
pingTask = new PingTimerTask(...);
try {
...
} finally {
/* this code even gets executed when an exception
* (for example an *InterruptedException*) was thrown:
*/
pingTask.cancel();
}
}
I have a series of tasks (i.e. Runnables) to be executed by an Executor.
Each task requires a certain condition to be valid in order to proceed. I would be interested to know if there is a way to somehow configure Executor to move tasks in the end of the queue and try to execute them later when the condition would be valid and the task be able to execute and finish.
So the behavior be something like:
Thread-1 take tasks from queue and run is called
Inside run the condition is not yet valid
Task stops and Thread-1 places task in the end of the queue and
gets next task to execute
Later on Thread-X (from thread pool) picks task again from queue condition is valid
and task is being executed
In Java 6, the ThreadPoolExecutor constructor takes a BlockingQueue<Runnable>, which is used to store the queued tasks. You can implement such a blocking queue which overrides the poll() so that if an attempt is made to remove and execute a "ready" job, then poll proceeds as normal. Otherwise the runnable is place at the back of the queue and you attempt to poll again, possibly after a short timeout.
Unless you have to have busy waiting, you can add a repeating task to a ScheduledExecutorService with an appropriate polling interval which you cancel or kill after it is "valid" to run.
ScheduleExecutorService ses = ...
ses.scheduleAtFixedRate(new Runnable() {
public void run() {
if (!isValid()) return;
preformTask();
throw new RuntimeException("Last run");
}
}, PERIOD, PERIOD, TimeUnit.MILLI_SECONDS);
Create the executor first.
You have several possibilites.
If I suppose that your tasks implement a simple interface to query their status (something like an enum with 'NeedReschedule' or 'Completed'), then implement a wrapper (implementing Runnable) for your tasks which will take the task and the executor as instanciation parameters. This wrapper will run the task it is bound to, check its status afterwards, and if necessary reschedule a copy of itself in the executor before terminating.
Alternatively, you could use an execption mechanism to signal the wrapper that the task must be rescheduled.
This solution is simpler, in the sense that it doesn't require a particular interface for you task, so that simple Runnable could be thrown in the system without trouble. However, exceptions incur more computation time (object construction, stack trace etc.).
Here's a possible implementation of the wrapper using the exception signaling mechanism.
You need to implement the RescheduleException class extending Throwable, which may be fired by the wrapped runnable (no need for a more specific interface for the task in this setup). You could also use a simple RuntimeException as proposed in another answer, but you will have to test the message string to know if this is the exception you are waiting for.
public class TaskWrapper implements Runnable {
private final ExecutorService executor;
private final Runnable task;
public TaskWrapper(ExecutorService e, Runnable t){
executor = e;
task = t;
}
#Override
public void run() {
try {
task.run();
}
catch (RescheduleException e) {
executor.execute(this);
}
}
Here's a very simple application firing up 200 wrapped tasks randomly asking a reschedule.
class Task implements Runnable {
#Override
public void run(){
if (Maths.random() > 0.5)
throw new RescheduleException();
}
}
public class Main {
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(10);
int i = 200;
while(i--)
executor.execute(new TaskWrapper(executor, new Task());
}
}
You could also have a dedicated thread to monitor the other threads results (using a message queue) and reschedule if necessary, but you lose one thread, compared to the other solution.
I have an event queue to process. A thread adds events to the queue.
I have created a runnable Task that in the run method does all which is necessary to process the event.
I have declared an Executors.newCachedThreadPool(); and I execute each Task.
public class EventHandler {
private static final ExecutorService handlers = Executors.newCachedThreadPool();
public void handleNextEvent(AnEvent event){
handlers.execute(new Task(evt));
}
public class Task implements Runnable{
#Override
public void run() {
//Event processing
}
}
public AnotherClass{
public void passEvent(AnEvent evt)//This is called by another thread
{
EventHandler.handleNextEvent(evt);
}
}
My problem is that if I call execute of the executor, my code will get the next event and run next runnable via the executor.
My purpose is to process next event from queue only after previous task has ended.
How would I know that the previous task has finished or not so that I know I can call handleNextEvent again?
Is having some status field updated by the Task a good idea?
Thanks
Executors.newCachedThreadPool() will create new threads on demand, so it's not what you want. You want something like Executors.newSingleThreadExecutor(), which will process the events one at a time, and queue up the rest.
See javadoc:
Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time.
I think Executors.newSingleThreadExecutor() and the submit() Method are the solution to your problem: http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html