The use of executor.shutdown() - java

Look at the following piece of code:
public void pinger()
{
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(runnable, start, rate, TimeUnit.SECONDS);
executor.shutdown();
}
Is there any use of writing the shutdown command in this case? Different clients would create their own runnable objects and invoke this function.

When you shutdown an executor, no new task will be accepted. Since you create a new one inside the pinger method every task has its own executor. A shutdown as you write will only free resource once the corrent task is terminated.

Some notes:
You should not create Executor for each client request.
Create Executor out side of client request and submit tasks to Executor
When you decide that you should not accept new tasks to Executor, then shutdown the executor. The right way of shutting down Executor is explained in below post:
How to forcefully shutdown java ExecutorService

Related

How to check if ExecutorService is "healthy" and working?

I'm developing a gui-less desktop application for my company that is planned to be always running in the background retrieving info from websites (through HtmlUnit) and updating some rows in the data base.
I'm using a ExecutorService to submit tasks where the web site is loaded so I can set a timeout. This way:
private ExecutorService taskExecutor = Executors.newFixedThreadPool(1);
private long timeout = 60000L;
private Page loadSite(Loader<Page> c) {
Page page;
Future<Page> result = taskExecutor.submit(c);
try {
page = result.get(timeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException | ExecutionException | InterruptedException ex) {
close();
result.cancel(true);
throw new HandledWebException(ex);
}
return page.getEnclosingWindow().getEnclosedPage();
}
The questions are:
Should I check if my taskExecutor object is able to schedule a task before the submit call, and reinstantiate it if necessary? (The prolonged execution time seems like a threat to me)
Do I have to shutdown and reinstantiate the taskExecutor if the submitted task fails to complete?
1) Should I check if my taskExecutor object is able to schedule a task before the submit call, and reinstantiate it if necessary?
2) Do I have to shutdown and reinstantiate the taskExecutor if the submitted task fails to complete?
For both the question no need
public static ExecutorService newFixedThreadPool(int nThreads)
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.

ThreadPoolTaskExecutor graceful shutdown

I'm using the Spring (v4) ThreadPoolTaskExecutor to execute some continuous runnable tasks. When the application shuts down, I want a graceful shutdown of the executor so that tasks have some time to complete their iteration before continuing the shutdown. If an active task completes its iteration prior to the executors wait time expiring (e.g. ThreadPoolTaskExecutor.setAwaitTerminationSeconds()), I do not want it to start another iteration. So far I have not been able to accomplish this. I have the following executor configuration:
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(30);
And my tasks are essentially setup as such:
myExecutor.execute(() -> {
while(true) {
doSomething();
}
});
I assume I need to set a flag in my thread when the executor shuts down so that the loop breaks. Is there another recommended approach?
Your run method is a endless loop, so you don't need to
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(30);
After removing above code, when you shutdown the thread pool, your working thread will be marked as iterrupted immediatly, but they will continue their work(unless they are sleeping, or InterruptionException will be thrown), and tasks in the cache queue will not be executed. You can just check this state and do not start next iteration.
myExecutor.execute(() -> {
while(true && !Thread.currentThread().isInterrupted()) {
doSomething();
}
});

What's the difference between canceling a periodic task via the future versus shutting down the executor service the task came from?

Difference between:
A)
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<> periodicTask = executorService.scheduleAtFixedRate(() -> {
try {
doSomething();
} catch (Exception e) {
log.error("Unhandled exception caught whilst doing minutely run", e);
}
}, initialDelay, PERIOD, TimeUnit.MILLISECONDS);
// In a shutdown hook:
periodicTask.cancel(true);
Does that cancel all the running tasks? Does it kill the ExecutorService?
B) The other way would be:
executorService.shutdown();
executorService.awaitTermination(....);
What's the difference?
Also how do I know how many tasks in the future the executorservice schedules?
Once I get the shut down signal I just want to run my scheduled task around 2 - 3 more times until I reach a certain condition. After that I want to kill it.
periodicTask.cancel(true);
The cancel method only stops the unstarted jobs and interrupts the running thread which then must return from the run() method.
executorService.shutdown();
The shutdown() method prevents clients sending more work to the executor service. This means all the existing tasks will run to completion.
executorService.awaitTermination(....);
This helps the application shut down gracefully. i.e. The executor service takes no more work and waits till all the executing jobs finish and then shuts-down.

Java Executors cancel job by timeout with inner executor

I have a big thread pool like
ThreadPoolExecutor pool = new ThreadPoolExecutor(cores, 50, 30L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3000));
I want to submit a task there. But I don't want to call future.get() at all, I want to submit it and forget.
But, I want my task to be cancelled in a certain time period. So I do the following:
public void run(){
FutureTask<WorkerWrapper> task = new FutureTask<>(()->worker.process(tmpArg));
executor.execute(task);
res=task.get(2, TimeUnit.MINUTES);
executor.shutdown();
}
In other words, I call executor inside executor. Is it safe and stable? Or can I cancel my task by timeout other way?
The only real way to achieve this, AFAIK, is to have a second ScheduledExecutor. You'd still need a handle of the Future but only pass it to the scheduled executor for cancellation.
Future<WorkedWrapper> task = executor.execute(() -> worker.process(tmpArg));
scheduledExecutor.schedule(() -> task.cancel(true), 2, TimeUnit.MINUTES);
There may be a more fluent way of handling this with CompleteableFutures but I am not 100% sure of that.
ScheduledThreadPoolExecutor has a method that allows to to schedule a runnable and get a future back. You can combine this with the timed get on the future:
ScheduedThreadPoolExecutor e = ...
Future<T> f = e.submit(new Runnable(){..},new T(){});
Object ignore = f.get(timeout, timeunit);

Schedule multiple tasks on multiple threads

I need to perform some data collection periodically, for that I want to create a task which requests some data from different servers. Some servers will take more time to process the request and return the response than others.
That's why I want to create a task for each server and execute the tasks async. If i'm using ScheduledExecutorService in the following way will each task execute in its own thread or all the tasks will be executed in the same thread?
What happens if a task is throwing an exception all the other scheduled tasks will fail?
this.scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
return new Thread(r, "collectionThread");
}
});
for (String url:urls){
this.scheduler.scheduleWithFixedDelay(new CollectorTask(url),
startupDelaySeconds,
scheduleRateSeconds,
TimeUnit.SECONDS);
}
You're using a single-threaded executor service, so all tasks are being executed sequentially. If any of them throws an exception, all next tasks executions are cancelled.
You could use
Executors.newScheduledThreadPool(4) // 4 is the max number of parallel jobs
... to allow parallel execution and wrap a body of a submitted job into
try {
...
} catch(Exception e){
logger.warn("exception during task execution", e);
}
to log errors without propagating them.
Minor delays (several milliseconds) are possible and depend on the OS, tasks will never execute earlier than their scheduled time. Task's execution can be delayed due to previous long runs or lack of free threads, but the following executions will be run by the original schedule: initialDelay + n * period.
Yes, what you do is create two thread executors. The first is a scheduled executor which takes a runnable that is meant to start your actual runnable. All this runnable does it create an instance of your task runnable and submit it to the real executor. That executor should just be a normal thread pool that will handle the tasks.
private final ScheduledExecutorService scheduledExecutor = Executors
.newSingleThreadScheduledExecutor();
private final ExecutorService executor = Executors.newCachedThreadPool();
private class SubmitTaskRunnable implements Runnable {
#Override
public void run() {
executor.execute(new TaskRunnable());
}
}
Schedule the SubmitTaskRunnable on your scheduled executor because that one will not throw any exceptions. Let your actual task run inside a cached executor will allow multiple tasks to run concurrently even if the previous ones have not finished.

Categories