In Android, I'm trying to start a thread that kills itself or is canceled by the executor after some timeout limit for example 20 seconds? So the runnable would only do its work for that many seconds than cancel...
How do I achieve this? I'm currently starting it as the following.
Executors.newSingleThreadScheduledExecutor().schedule(myRunnable, 0, TimeUnit.MILLISECONDS);
My runnable looks like this
static class MyRunnable implements Runnable {
MyRunnable(Helper _helper) {
helper = _helper;
}
public void run() {
}
}
If you want to stop a task that has already been submitted to an ExecutorService then you'll need to deal with Future objects.
Like this answer:
Stop a Runnable submitted to ExecutorService
Basically you will submit a Runnable and get back a Future object that you can use to cancel it.
Specific to your concern: Stop one task in 20 seconds you could use handoff the Future object from the first task to another like so:
ExecutorService executor = Executors.newSingleThreadScheduledExecutor();
// Schedule your audio processing job like normal.
final Future<?> future = executor.submit(new MyAudioProcessingRunnable())
// Schedule the cancelation to happen in 20 seconds.
executor.schedule(new Runnable() {
if (!future.isCancelled() && !future.isDone()) {
// Cancel and interrupt any blocking calls.
future.cancel(true);
}
}, 20, TimeUnit.Seconds);
IMPORTANT - You must have code in your MyAudioProcessingRunnable to support cancelation.
Related
I Used ExecutorService that interrupts tasks after a timeout.I use a ScheduledExecutorService for this. First I submitted the thread and it once to begin immediately and retain the future that is created. After that i use ScheduledExecutorService as a new task that would cancel the retained future after some period of time.
//Start Spring executor to submit tasks
ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) ApplicationContextProvider.getApplicationContext().getBean("taskExecutor");
CompletionService completionService = new ExecutorCompletionService(taskExecutor);
//End Spring executor to submit tasks
// Start ScheduledExecutorService to submit returned future object to timeout
ScheduledExecutorService executor = Executors.newScheduledThreadPool(Integer.parseInt(config.getProperty("DBPOLLER_COREPOOLSIZE")));
final Future<String> future = completionService.submit(batchJob); // Submit actual task and get future
// submit future
executor.schedule(new Runnable() {
public void run() {
future.cancel(true);
}
}, dbPollerTimeOut, TimeUnit.MINUTES);
int count = taskExecutor.getActiveCount();
if (count == 0) {
taskExecutor.shutdown();
executor.shutdown();
finalExitStatus = 0;
break;
}
I have implemented the solution which is in below url:
ExecutorService that interrupts tasks after a timeout, it was working fine, until timeout, but once timeout happens, it cancels all theenter code here tasks i ThreadPool which is not acceptable. I need to cancel only tasks that are long running and reach timeout.
Any idea how to achieve this?
It is not clear what your CompletionService is, and you are submitting your batchJob on it, so it is hard to tell exact root cause of your problem. But ideal scenario of submitting few tasks and cancelling them after some time, is to use ScheduledExecutorService for both purposes.
So, can try submitting the batchJobon instance of ScheduledExecutorService i.e. executor.
final Future<String> future = executor.submit(batchJob); // Submit actual task and get future
EDIT UPDATE: Important change you SHOULD do in your code
I see that you are never stopping your ScheduledExecutorService which is wrong because resources it occupies will never be released until you stop it. So, your updated code should be as below:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(Integer.parseInt(config.getProperty("DBPOLLER_COREPOOLSIZE")));
final Future<String> future = executor.submit(batchJob); // Submit actual task and get future
executor.schedule(new Runnable() {
public void run() {
future.cancel(true);
executor.shutdownNow();
}
}, dbPollerTimeOut, TimeUnit.MINUTES);
I currently have the main method which collects tasks. After the tasks are collected, the ExecutorService is being called with fixed thread pool size. The tasks are iterated and submitted to the executor.
But I need to refresh the tasks and if there is any new tasks available I am adding it to the executor. But if one of the thread is free without any tasks to be allocated from the queue, I want that thread to manually notify my main thread to refresh the events and submit to executor even before the manual refresh is happening from my end. How can i achieve this. Thanks
Sample Code
public class Sample{
Map<String, List<Integer>> tasks;
ThreadPoolExecutor executor;
public static void main(String[] args) {
executor = Executors.newFixedThreadPool(2);
tasks = Collections.synchronizedMap(new HashMap<String, List<Integer>>());
tasks = Tasks.refresh(); //This will get me a new set of data to be processed
invokeexecutor();
}
public void invokeexecutor(){
for(String key: tasks.keyset())
{
executor.submit(new TaskRunnable(tasks.get(key));
}
tasks.clear(); //Remove the allocated tasks from the collection
}
}
public class TaskRunnable implements Runnable{
public void run(){
//Do some logic
}
}
In this case I want my data in the tasks to be continuously refreshed after 10 seconds lets say or if any of the executor thread is free this refresh must happen and a new runnable mus tbe assinged to the thread.
But if one of the thread is free without any tasks to be allocated from the queue, I want that thread to manually notify my main thread to refresh the events and submit to executor even before the manual refresh is happening from my end. How can i achieve this.
There are a couple of ways you can achieve this easily. One way is to create the `ThreadPoolExecutor' yourself.
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
Then have a polling thread that watches the ThreadPoolExecutor class to determine if there are any free threads. Something like:
while (!Thread.currentThread().isInterrupted()) {
// sleep a bit
Thread.sleep(1000);
if (executor.getActiveCount() < 2) {
// add tasks here
}
}
A polling thread is a bit gross however. Another idea which is a bit simpler would be to use a fixed size queue of tasks and then always be trying to add the tasks to the list. This will block if the queue is full. Something like:
// create a limited blocking queue
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(10));
while (!Thread.currentThread().isInterrupted()) {
// add tasks here which will block if too many in the queue
}
You can try to override afterExecute method in ThreadPoolExecutor. It is called when a thread in a pool executed a task.
class MyThreadPoolExecutor extends ThreadPoolExecutor {
public MyThreadPoolExecutor {
super(/*Call one of TheadPoolExecutor constructors*/)
}
protected afterExecute(Runnable r, Throwable t) {
// Notify main thread here
}
}
I am writing code where I need to make sure that no threads are currently running in a thread pool before I commit results (to avoid losing data I should have put in the commit). For that, I'm using:
while (_executor.getActiveCount() > 0)
{
try
{
Thread.sleep(10); // milliseconds
}
catch (InterruptedException e)
{
// OK do nothing
}
}
But a colleague pointed out in review that the doc for getActiveCount states:
Returns the approximate number of threads that are actively
executing tasks.
So, is there a risk I would get out of the while loop while there are still active threads in the pool? If so, what would be the correct way to wait for all my worker threads to be done?
Edit: To give some more context: this is an online system, where the task that contains the executor service is left running indefinitely. Work comes in via a messaging system, is put on a thread in the executor, which doesn't need any synchronization, and works come out into another queue for the messaging system. I don't want to kill the executor to wait for completion of tasks.
You might want to consider using a CompletionService (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html).
A CompletionService wraps an ExecutorService and returns a Future when tasks are submitted. By maintaining a list of these Futures, you can see if the jobs that you're waiting on have completed. It also has the additional advantage that you can have others use the same ExecutorService since you have some means of accounting,
_executor.awaitTermination(); should do the job. Now, it won't actually wait for the threads to shutdown, but rather it would wait for all available tasks to terminate.
You could also provide keepAliveTime to a thread pool constructor to instantly terminate idle threads:
ExecutorService executor = new ThreadPoolExecutor(0, 10, 0L /* keepAlive */,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
To notify a thread that it should clean up and terminate, use the interrupt method.
t.interrupt();
and it is good to print or have log of your errors from catch block.
When tasks are submitted to the executor, they return Futures, which indicate when they complete. That is the preferred mechanism to use.
You can use JDK ExecutorService shutdown/awaitTermination.
Use case: need to cleanup thread-locals in pool threads upon their completion and this cleanup can take long (e.g. connection close). Only after that the main thread can continue.
A worker thread can register itself in some collection. For that override start() and run() and pass a custom thread factory to ThreadPoolExecutor:
class MyThreadFactory implements ThreadFactory {
#Override
public Thread newThread(final Runnable r) {
return new MyThread(r);
}
...
class Some {
void waitAllThreads() {
Thread worker;
while ((worker = workerThreads.poll()) != null) {
worker.join();
}
}
...
class MyThread extends Thread {
#Override
public synchronized void start() {
if (getState() == State.NEW) {
some.workerThreads.offer(this);
}
super.start();
}
#Override
public void run() {
try {
super.run();
} finally {
some.workerThreads.remove(this);
}
}
...
i have a ScheduledExecutorService (with newScheduledThreadPool( 1)) where i add tasks like this:
myTask = scheduler.scheduleAtFixedRate(new Runnable() {
#Override public void run() {
// do work
}
},
delay,
interval,
TimeUnit.MILLISECONDS );
I have a list of all my tasks. If i for example want to remove a task i can do this (e.g. the first task)
myTaskList.get(0).getTask().cancel(true);
My problem now is that if the task i want to cancel is currently running in the scheduler thread i have to wait in the main-thread till the task is canceled. I thought i could do this with get() like this:
myTaskList.get(0).getTask().cancel(true);
myTaskList.get(0).getTask().get();
but my main-thread goes on without waiting for the task code to finish.
For clarity, what i want is basically this:
User wants to cancel task
If to be canceled Task is the one currently running in the scheduler thread the main-thread have to wait till the task is no longer the one executing in the scheduler thread
If I truly understood your mean, you want main method waits for child thread to finish/stop. Is it true? If so, You can use method join() in the main method. This method forces main method to wait for child thread to stop/finish. This method is in class java.lang.Thread.
I don't think this would work in practice. When you attempt a get() on a canceled Future it will throw a CancellationException as per API
#throws CancellationException - if the computation was cancelled
What you could try is to map the Future with a CountdownLatch maybe something like this
class LatchedFuture{
volatile Future future;
final CountdownLatch latch = new CountdownLatch(1);
}
final LatchedFuture latchedFuture = new LatchedFuture();
latchedFuture.future = scheduler.scheduleAtFixedRate(new Runnable() {
#Override public void run() {
// do work
latchedFuture.latch.countDown();
}
},
delay,
interval,
TimeUnit.MILLISECONDS );
Then when you want it to finish.
myTaskList.get(0).getTask().future.cancel(true);
myTaskList.get(0).getTask().latch.await();
I'm writing a swing application with HttpClient and I need a way to make a download list because I need to wait 1 minute (for example) before starting a new download.
So I would like to create a waiting list of threads (downloads).
I would have a class that takes a time parameter and contains a list of threads and when I add a thread in the list it starts if there is no running thread. Otherwise it waits for its turn.
Is there any tool to do that ?
Thanks a lot for your help.
Yes. ScheduledExecutorService. You can create a fixed length service via Executors.newScheduledThreadPool(corePoolSize). When you are ready to submit the task to wait the amount of time just submit it to ScheduledExecutorService.schedule
ScheduledExecutorService e = Executors.newScheduledThreadPool(10)
private final long defaultWaitTimeInMinutes = 1;
public void submitTaskToWait(Runnable r){
e.schedule(r, defaultWaitTimeInMinutes, TimeUnit.MINUTES);
}
Here the task will launch in 1 minute from the time of being submitted. And to address your last point. If there are currently tasks being downloaded (this configuration means 10 tasks being downloaded) after the 1 minute is up the runnable submitted will have to wait until one of the other downloads are complete.
Keep in mind this deviates a bit from the way you are designing it. For each new task you wouldnt create a new thread, rather you would submit to a service that already has thread(s) waiting. For instance, if you only want one task to download at a time you change from Executors.newScheduledThreadPool(10) to Executors.newScheduledThreadPool(1)
Edit: I'll leave my previous answer but update it with a solution to submit a task to start exactly 1 minute after the previous task completes. You would use two ExecutorServices. One to submit to the scheuled Executor and the other to do the timed executions. Finally the first Executor will wait on the completion and continue with the other tasks queued up.
ExecutorService e = Executors.newSingleThreadExecutor();
ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(1)
public void submitTask(final Runnable r){
e.submit(new Runnable(){
public void run(){
ScheduledFuture<?> future= scheduledService.schedule(r, defaultWaitTimeInMinutes, TimeUnit.MINUTES);
future.get();
}
});
}
Now when the future.get(); completes the next Runnable submitted through submitTask will be run and then scheduled for a minute. Finally this will work only if you require the task to wait the 1 minute even if there is no other tasks submitted.
I think this would be a wrong way of going about the problem. A bit more logical way would be to create "download job" objects which will be added to a job queue. Create a TimerTask which would query this "queue" every 1 minute, pick up the Runnable/Callable jobs and submit them to the ExecutorService.
You could use the built-in ExecutorService. You can queue up tasks as Runnables and they will run on the available threads. If you want only a single task to run at a time use newFixedThreadPool(1);
ExecutorService executor = Executors.newFixedThreadPool(1);
You could then append an artificial Thread.sleep at the beginning of each Runnable run method to ensure that it waits the necessary amount of time before starting (not the most elegant choice, I know).
The Java Concurrency package contains classes for doing what you ask. The general construct you're talking about is an Executor which is backed by a ThreadPool. You generate a list of Runables and send them to an Executor. The Executor has a ThreadPool behind it which will run the Runnables as the threads become available.
So as an example here, you could have a Runnable like:
private static class Downloader implements Runnable {
private String file;
public Downloader(String file) {
this.file = file;
}
#Override
public void run() {
// Use HttpClient to download file.
}
}
Then You can use it by creating Downloader objects and submitting it to an ExecutorService:
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (String file : args) {
executorService.submit(new Downloader(file));
}
executorService.awaitTermination(100, TimeUnit.SECONDS);
}
It is maybe not the best solution but here is what I came up with thanks to the answer of John Vint. I hope it will help someone else.
package tests;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class RunnableQueue
{
private long waitTime;
private TimeUnit unit;
ExecutorService e;
public RunnableQueue(long waitTime, TimeUnit unit) {
e = Executors.newSingleThreadExecutor();
this.waitTime = waitTime;
this.unit = unit;
}
public void submitTask(final Runnable r){
e.submit(new Runnable(){
public void run(){
Thread t = new Thread(r);
t.start();
try {
t.join();
Thread.sleep(unit.toMillis(waitTime));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
public static void main(String[] args) {
RunnableQueue runQueue = new RunnableQueue(3, TimeUnit.SECONDS);
for(int i=1; i<11; i++)
{
runQueue.submitTask(new DownloadTask(i));
System.out.println("Submitted task " + i);
}
}
}