I have a Servlet which recieves a request, has to process 5 tasks (Grab data Form external Servers) and send all the data back to the client ordered.
How to process the 5 Task simultaneously and continue with the servlet code after all 5 tasks are completed?
You can use CoundDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
sample code:
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(5); // 5 tasks
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final int threadNumber;
// you can pass additional arguments as well
Worker(CountDownLatch startSignal, CountDownLatch doneSignal,
int threadNumber) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.threadNumber = threadNumber;
}
public void run() {
try {
startSignal.await();
doWork(); // actual work to be performed here
doneSignal.countDown();
} catch (InterruptedException ex) {
LOGGER.error(ex);
}
}
}
// 5 new threads are started
for(int i=1;i<=5;i++){
new Thread(new Worker(startSignal, doneSignal, i)).start();
}
startSignal.countDown(); // let all threads proceed
try {
doneSignal.await(); // wait for all to finish
// all 5 tasks are finished and do whatever you want to do next
} catch (InterruptedException interruptedException) {
LOGGER.error(interruptedException);
}
Read more... and Find more examples...
Another option is the ExecutorService. There are a variety of examples available including the following:
How to wait for all threads to finish, using ExecutorService?
ExecutorService, how to wait for all tasks to finish
Here is some example code taken from the first link found above:
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
5 seconds is too long, it might take up the web server resource, you can let the client to send a request A, which trigger your 5 seconds task, but it don't wait, return immediately.Since you know it will take 5 seconds, you can send another request B, 5 seconds later, to get the data. If data not ready yet, you can request after another 5 seconds, until MAX_RETRY_COUNT (defined by yourself) reached.
Related
I have written a piece of code . How can I get that code to run for certain duration repeatedly, say for 10 second?
The ExecutorService seems to provide methods which execute tasks until they are either completed or else a timeout occurs (such as the invokeAll).
You can give a try to Quartz Job Scheduler
Quartz is a richly featured, open source job scheduling library that
can be integrated within virtually any Java application - from the
smallest stand-alone application to the largest e-commerce system.
Quartz can be used to create simple or complex schedules for executing
tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks
are defined as standard Java components that may execute virtually
anything you may program them to do. The Quartz Scheduler includes
many enterprise-class features, such as support for JTA transactions
and clustering.
If you are familiar with Cron in Linux , this will be a cakewalk for you .
Use a worker and start it in a thread, wait in the main thread for the specific time and stop the worker after this.
MyRunnable task = new MyRunnable();
Thread worker = new Thread(task);
// Start the thread, never call method run() direct
worker.start();
Thread.sleep(10*1000); //sleep 10s
if (worker.isAlive()) {
task.stopPlease(); //this method you have to implement
}
Not too sure why people downvoted the question. Be sure to in the future provide some sample code. Your answer however is simple here. Create a new thread to watch the wait. In simple code:
public class RunningClass {
public static void runThis(){
TimerThread tt = new TimerThread();
tt.timeToWait = 10000;
new Thread(tt).start();
while (!TimerThread.isTimeOver){
\\Code to execute for time period
}
}
class TimerThread implements Runnable {
int timeToWait = 0;
boolean isTimeOver = false;
#override
public void run(){
Thread.sleep(timeToWait);
}
}
The code above can be put in the same class file. Change the 10000 to whatever time you require it to run for.
You could use other options, but it would require you to have knowledge on workers and tasks.
not sure what was the exact requirement, but
if your req was to cancel only a long running task
you could use ExecutorService & Future (in jdk 5) as follows.
ExecutorService fxdThrdPl = Executors.newFixedThreadPool(2);
// actual task .. which just prints hi but after 100 mins
Callable<String> longRunningTask = new Callable<String>() {
#Override
public String call() throws Exception {
try{
TimeUnit.MINUTES.sleep(100); // long running task .......
}catch(InterruptedException ie){
System.out.println("Thread interrupted");
return "";
}
return "hii"; // result after the long running task
}
};
Future<String> taskResult = fxdThrdPl.submit(longRunningTask); // submitting the task
try {
String output = taskResult.get(***10**strong text**, TimeUnit.SECONDS***);
System.out.println(output);
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (TimeoutException e) {
***taskResult.cancel(true);***
}
I have a series of different "tasks" to be done using the same thread pool. I want to measure the time it takes to perform each task, but for that I need to wait for every task in the "task" (sorry for ambiguity) to finish.
When there's just one task I would normally do this:
ExecutorService e = Executors.newCachedThreadPool();
for (int i=0; i<100; ++i)
e.submit(target);
e.shutdown();
while (!e.isTerminated());
But since there will be several task submitted to the pool, I can't it down. All the methods that have something to do with waiting for the tasks to finish mention "after shutdown request". Well, what if I don't want to shut it down, but wait for all the threads to finish and then submit more tasks?
This is what I want to do:
ExecutorService e = Executors.newCachedThreadPool();
for (int i=0; i<100; ++i)
e.submit(target);
// wait for all targets to finish
for (int i=0; i<100; ++i)
e.submit(target); // submit different tasks
// wait... and so on
I thought of shutting the pool down and then "waking it up" again using prestartAllCoreThreads, but then I realized this was not an ExecutorService method but a ThreadPoolExecutor method. Could this be a solution? Shutting it down, waiting, and then activating the pool again? Seems a bit ugly to me.
I also thought that the most natural thing to do was to use a CyclicBarrier, but it seems too a specific way of doing this, while I think it would be the most logical thing to be able to use any ExecutorService for what I'm trying to do.
Is there any way I could stick to ExecutorServices and wait for all the tasks to finish?
Use CyclicBarrier for the work you need like so :
// the optionalRunnable can collect the data gathered by the tasks
CyclicBarrier b = new CyclicBarrier(numberOfTasks,optionalRunnable)
Task yourTaks = new Task(...., b);
// inside the run method call b.await() after the work is done;
executor.submit(yourTaks);
Optionally , you can also call await in the main thread and instantiate the barrier to numTasks + 1 . That way you are sure you're resubmitting tasks to the executor only after it's done processing the current batch
You can await the termination of that ExecutorService.
ExecutorService executor = Executors.newCachedThreadPool();
//do your stuff
try {
executor.shutdown();
executor.awaitTermination(5, TimeUnit.MINUTES);
} catch (InterruptedException e) {
//handle
}
Or use a CountDownLatch:
CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
try {
latch.await();
} catch (InterruptedException E) {
// handle
}
and within your task (enclose in try / finally)
latch.countDown();
You could create a TaskListener interface which you pass into each task. Each task notifies the TaskListener when they start and stop. Then you can create a TimingTaskListener implementation which maintains a ConcurrentMap of the durations which can be queried later.
public interface TaskListener {
void onStart(String taskId);
void onEnd(String taskId);
}
public class Task implements Runnable {
private TaskListener taskListener;
private String taskId;
public Task(String taskId, TaskListener taskListener) {
this.taskId = taskId;
this.listener = listener;
}
public void run() {
listner.onStart(taskId);
try {
doStuff();
} finally {
listener.onEnd(taskId);
}
}
}
// TODO: Implement TimingTaskListener to save durations to a ConcurrentMap
TimingTaskListener timingListener = new TimingTaskListener();
Runnable task1 = new Task("task1", timingListener);
Runnable task2 = new Task("task2", timingListener);
Future<?> f1 = e.submit(task1);
Future<?> f2 = e.submit(task2);
// futures block until the task is finished.
// You could also use a CountDownLatch to achieve the same
f1.get();
f2.get();
long time1 = timingListener.getDuration("task1");
long time2 = timingListener.getDuration("task2");
Anybody able to provide me with an example of getting a RejectedExecutionException
Possibly a real life example.
Thanks in advance.
Anybody able to provide me with an example of getting a RejectedExecutionException Possibly a real life example.
Sure. The following code submits 2 jobs into a thread-pool with only 1 thread running. It uses a SynchronousQueue which means that no jobs will be stored in the job queue.
Since each job takes a while to run, the 2nd execute fills the queue and throws a RejectedExecutionException.
// create a 1 thread pool with no buffer for the runnable jobs
ExecutorService threadPool =
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
// submit 2 jobs that take a while to run
/// this job takes the only thread
threadPool.execute(new SleepRunnable());
// this tries to put the job into the queue, throws RejectedExecutionException
threadPool.execute(new SleepRunnable());
public class SleepRunnable implements Runnable {
public void run() {
try {
// this just sleeps for a while which pauses the thread
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
Sending tasks to an executor after calling shutdown( on it will throw this exception.
In addition, if the executor uses a bounded blocking queue if the queue is full submitting the task will not block but will fail-fast with the exception.
This question has already been asked and answered :
What could be the cause of RejectedExecutionException
Submitting tasks to a thread-pool gives RejectedExecutionException
This code gives you the error because we try to launch the task but the executor is shut down you can refer to the link above for further explications the answer looked pretty complete:
public class Executorz {
public static void main(String[] args) {
Executorz ex = new Executorz();
ExecutorService es = Executors.newFixedThreadPool(10);
for (int i = 0; i<100 ; i++){
System.out.println("Executed");
es.execute(ex.getNewCountin());
if (i==20)
es.shutdown();
}
}
public Countin getNewCountin(){
return new Countin();
}
public class Countin implements Runnable {
#Override
public void run() {
for (double i =0; i<1000000000 ; i++){
}
System.out.println("Done");
}
}
}
I have the following code hashed out:
public class MyCallable implements Callable<Long> {
#Override
public Long call() throws Exception {
// Do stuff...
}
}
public class MyController {
private ExecutorService executor = Executos.newCachedTreadPool();
public Long concurrentDoStuff() {
List<MyCallable> workers = makeWorkers();
List<Long> allResults = new ArrayList<Long>();
for(MyCallable worker : workers) {
Future<Long> workerResults = executor.submit(worker);
try {
allResults.add(workerResults.get());
} catch(InterruptedException ie) {
// Handle...
} catch(ExecutionException ee) {
// Handle...
}
}
// Question: how do I pause here and wait for all workers to finish?
}
}
After the for-loop, I want to wait for all workers to finish before proceeding any further. What's the best/safest/most-efficient way to do this? Thanks in advance!
Use a CountDownLatch.
Initialize it with the number of workers
Pass a reference to the latch in the worker constructor
When the worker is done, call countDown
Call await in the main thread and it will block until the workers are done.
This is a more general-purpose solution than using methods on the executor service.
You must shut the Executor down with shutDown and then wait until all jobs have been processed with awaitTermination.
You can call:
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE , TimeUnit.NANOSECONDS);
This will wait (almost) indefinitely for the tasks to complete.
There is a handy method.
ExecutorService.invokeAll(List<Callable> callables);
It will return List<Future> objects so that you can get the returned objects of all your individual call() methods.
You can get the instance of ExecutorService by calling Executors.new....()
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);
}
}
}