I have a single threaded executor which reads emaling jobs from a blocking queue as I have to send emails sequentially. Sometimes the java mail sender's sendMail() call hangs up. Since I have just 1 thread sending emails, I don't want to freeze this indefinitely when mail server call hangs.
So, effectively I want to run the emailing tasks with a defined timeout after which it should be cancelled.
The way I have done this is with Java 8 Future class. So I submit the task to my single threaded executor, get the future object in return and then schedule future.cancel() in a separate scheduledExecutor. With the scheduledExecutor, my main thread which is dequeing the emailing jobs from the blocking queue remains async.
But this approach has a problem. Let's say there are 5 objects to be emailed sitting in the blocking queue. And let's assume I have a timeout of 5 secs after which future.cancel() would be called. My async dequeuing thread loops through quickly and puts all 5 objects into the single threaded executor's queue. And when my single thread picks the first job and calls JavaMail's->sendMail(), the call hangs. After 5 secs, the future.cancel() would be called on this task. But my other 4 jobs were also in the executor's queue for the last 5 secs, so their future.cancel() would also be called even before they were processed by the single thread!
Here is my existing implementation
// process sequentially using single 'EmailMain'thread.
Future future = singleThreadExecutor.submit( () -> {
try {
mailService.sendEmail( tradeConfirmationInputFields, tradeConfirmFile );
} catch ( MessagingException | IOException e ) {
log.error( "Found error", e );
return;
}
} );
// timeout the single 'EmailMain' thread if not completed within allowed time.
taskTimeoutScheduledExecutor.schedule( () -> {
future.cancel( true );
}, 5000L, TimeUnit.MILLISECONDS );
} catch ( InterruptedException e ) {
log.error( "Error while emailing tradeConfirmation", e );
}
I want each of emailing jobs to to be processed through the'EmailMain' single thread in sequence and the timer for their timeout to start when the single threads starts processing them and NOT when the jobs are added to the singleThreadedExecutor's queue. Is there any clean solution in Java 8? I know in Java 9, there is some simple option like the below (taken from
https://www.deadcoderising.com/java-9-handle-timeouts-asynchronously-using-completablefutures-ortimeout-and-completeontimeout/
):
CompletableFuture.supplyAsync(this::getArticles)
.orTimeout(1, TimeUnit.MINUTES);
Related
I'm currently working on a discord bot just to mess around with, but have used SES in the past for other things, but I always struggle to disable/enable the SES, calling ses.shutdown(); does not work and the runnable continues, and if I did shutdown im not sure how to restart it.
Here is my current code...
private final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
protected void startRainbow(Role rle) {
roleRainbow[] colors = roleRainbow.values();
HashMap<String, Integer> map = new HashMap<>();
map.put("loop", 0);
Runnable r = () -> {
if(map.get("loop") >= colors.length) {
map.put("loop", 0);
}
rle.getManager().setColor(Color.decode(colors[map.get("loop")].toString())).queue();
System.out.println("color is: " + colors[map.get("loop")].toString());
System.out.println("color from role: " + rle.getColor());
map.put("loop", map.get("loop") + 1);
};
ses.scheduleAtFixedRate(r, 1L, 1, TimeUnit.SECONDS);
}
There are two angles to this problem:
Interrupting a currently-running thread.
Graceful shut down of a scheduled executor service.
The first has been addressed many many times on Stack Overflow already. In brief: You must signal a thread that you want it to interrupt itself. That thread's task must be coded is such a way to look for the interruption signal.
For the second, there are two steps involved:
You first tell the scheduled executor service that you want to stop any further executions of future-scheduled tasks. We do this with a call to shutdown. This call does not interrupt any currently existing task (see above paragraph).
Alternatively, you may call shutdownNow. This call may signal the running task to interrupt, but no guarantees. The behavior is implementation-defined.
After requesting the service to stop further scheduling, you can watch to see if the service does indeed stop after a reasonable amount of time has passed. We do this with a call to awaitTermination.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
ses.scheduleAtFixedRate( task , initialDelay , period , timeUnit ) ;
…
ses.shutdown() ;
boolean terminated = false ;
try { terminated = ses.awaitTermination( 1 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { e.printStackTrace(); }
if( ! terminated ) { … Houston, we have a problem. … }
The call to shutdown (and shutdownNow) does not block; it does not wait for anything to happen, and does not wait for tasks to end.
The call to awaitTermination does block until either:
Scheduled executor service finishes its last running task, and ends.
The specified time-out elapses.
Test for the boolean returned by the awaitTermination call. To quote the Javadoc:
true if this executor terminated and false if the timeout elapsed before termination
You asked:
if I did shutdown im not sure how to restart it.
Once shutdown, the scheduled executor service is done. To schedule tasks for execution, you must instantiate a new scheduled executor service.
Be aware that a scheduled executor service with no tasks to execute takes very little memory or CPU. So no need to shutdown if you might later need the service.
However, be sure to always shutdown your executor services before your app ends. Otherwise the backing thread pool(s) may continue running indefinitely, like a zombie 🧟♂️.
I am trying to use fixed thread pool using executor framework. Each runnable instance submitted to the executor is worker thread which process a java result set. For every iteration of the result set I have to call rest webservice which used the oauth token. The oauth token is to be refreshed after every 50 min and need to be shared among all the runnable submitted to the executor.I am also using scheduled executor which execute after every 50 minutes but sometimes it is called correctly and some time not due to which the rest web service fails as it used the expired token in its header. I need to ensure that the scheduled service must be called after every 50 min without fail. But I am stuck on this. Also I need some mechanism that after the group of rest web service call is completed then only the new web service calls should be made while iterating the result set.
ThreadPoolExecutor executorPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
WorkerThread wt1=new WorkerThread(conn,Queries.getAddressInfo("AL"),oauth_token,restTemplate);
WorkerThread wt2=new WorkerThread(conn,Queries.getAddressInfo("AK"),oauth_token,restTemplate);
executorPool.execute(wt1);
executorPool.execute(wt2);
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new Runnable() {
public void run() {
System.out.println("token service");
String url="";
try {
url = WebServicePropertyFileReader.getOauthUrl()+String.format(urlToGetOauthToken, WebServicePropertyFileReader.getClientId(),
WebServicePropertyFileReader.getClientSecret());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Layer7Token token=restTemplate.postForObject(url, null, Layer7Token.class);
GlobalTokenAccessor.oauth_token=token.getAccessToken();
}
},
50,
TimeUnit.MINUTES);
There are two issues :
Schedule schedules it only one time.
You should use scheduleAtFixedRate to schedule periodic tasks. There is no guarantee that the thread will get scheduled within 50 minutes. So, you may want to schedule the refresh every 49 minutes or so.
Secondly, you should control the access to the shared variable though a synchronized write and read methods. Otherwise, the read thread may read incorrect values.
I have a method producer.postMessage(message) which sends a message to some queue. If for some reason the message could not be sent in a period of time I want this task to be canceled. I came up with the implementation below. My question is if there is an interrupt can I be sure the Future task/ executor service are all shutdown and if not what changes need to be made to make this working without any threads not being terminated.
Thanks a lot
public void postMessage(final Object object)
{
LOG.debug("postMessage object " + object.getClass().getSimpleName());
Message message = new Message("task", 10, object);
try
{
ExecutorService ex = Executors.newSingleThreadExecutor();
Future<?> f = ex.submit(new Runnable()
{
public void run()
{
producer.postMessage(message);
LOG.debug("Finished sending message for " + object.getClass().getSimpleName());
}
});
f.get(5, TimeUnit.SECONDS);
ex.shutdown();
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
LOG.error("Could not deliver message to the queue, Check AMQ is running");
}
}
The shutdown() method on an Executor will stop it from accepting new tasks, but attempts to complete the running tasks. You should use method shutdownNow() to have the Executor request that currently running tasks are stopped.
This may not be necessary however, if you use method cancel(boolean mayInterruptIfRunning) on the Future object. f.get(5, TimeUnit.SECONDS) will wait at most 5 seconds for completion of the tasks before returning. Since you submit a Runnable rather than a Callable, the return will always be null; Runnables can't return a result, while Callables can. What you can do is call isDone() on the Future after the get with a 5 second timeout, and if it returns false, it means the tasks has not completed. In that case you can then call cancel(true) on the Future to attempt to cancel the task. The true argument indicates that you'll allow the Future to interrupt the thread if it is running. You may want to catch InterruptedExceptions in your Runnable and log them. Note however that not every call may respond to interrupt requests (for example, some I/O operations may not, while a lot of Java NIO stuff does).
Calling the shutdown on the executor may no longer be necessary, since it's only used for a single task and should have no other waiting or running tasks, but it's probably still good form.
So your code would become:
f.get(5, TimeUnit.SECONDS);
if (!f.isDone())
f.cancel(true);
ex.shutdown();
I am trying to implement comet approach for Facebook like browser push notifications in following manner:
HTTP request is made to a simple Servlet using AJAX, it gets submitted to java.util.concurrent.Executor (using AsyncContext) and HTTP thread gets freed immediately. This request is picked by a background thread.
This background worker thread in the thread pool keeps checking for new notification every 30 seconds (Queries database). If there is any notification, a response it sent. Else after certain timeout i.e. 5 minutes, a "No Notification" response is sent. Client immediately makes a new request and the process is repeated.
Problem here is that I am using Thread.sleep(30000) for periodically checking the data.
There is still one thread occupied per request. This time (30 sec) is wasted and the thread remains un-available to cater any other request.
Is there any technique which I can use, to return the thread to pool immediately after it has checked for new notification? And then some other available thread from the pool does the same after 30 secs to check notifications and so on?
Code goes like this:
// Creation of a global async Executor on ServletContextListener. contextInitialized
Executor executor =
new ThreadPoolExecutor(1, 1, 50000L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(100));
// Delegate the request to async thread
executor.execute(new RunnableClass(asyncContext));
// In RunnableClass.run() method
while(timeout5Min)
{
boolean newNotificationPresent = checkIfNotificationPresent(reqId);
if(!newNotificationPresent)
Thread.sleep(30000);
}
// send response
Can ScheduledThreadPoolExecutor somehow be used in such case? Any other technique?
If you are looking for Thread efficiency, you should look at actors.
Have a look at Akka
Otherwise, don't sleep, schedule a recheck using a java.util.Timer
I am using java.util.concurrent package to create a parallel program. I have 2 threads:
thread-1 which invokes webservice method-1, and
thread-2 which invokes webservice method-2.
I am specifying a thread execution timeout - suppose if thread-1 does not complete execution within the specified timeout then I have to intercept thread-1, continue the execution with thread-2 and display thread-2 results in jsp (note: if both threads take too much time to process the requests then I don't want the UI to wait until they complete).
I tried with the code below but it throws an InterruptedException. How can I proceed with other tasks when one task takes more mire?
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletionService<ArrayList<AvailableWeatherDetailVO>> compService = new ExecutorCompletionService<ArrayList<AvailableWeatherDetailVO>>(executor);
// Start amazonTask using thread-1
try{
compService.submit(amazonTask).get(20, TimeUnit.MILLISECONDS);
amazonFuture = compService.take();
amazonFinalList =(ArrayList<AvailableWeatherDetailVO>)amazonFuture .get() }
catch (TimeoutException e) {
compService.submit(amazonTask).cancel(true);
//throw new TimeoutException("Thread not executed with in speifed time");
}
// Start googleTask using thread-2
try{
compService.submit(googleTask).get(100, TimeUnit.MILLISECONDS);
googleFuture = compService.take();
googleFinalList =(ArrayList<AvailableWeatherDetailVO>)googleFuture .get() }
catch (TimeoutException e) {
compService.submit(googleTask).cancel(true);
//throw new TimeoutException("Thread not executed with in speifed time");
}
It is not clear if you mean thread2 only begins execution if thread1 fails.
Or, are they both executing, but you want to use the result of thread1 if it completes, else you want to use the result of thread2
It sounds to me like you should attach thread 1 to a Future. Then get the result (from your main thread) with a timeout. If the Future.get() times out, then get the result from the second thread.
Not sure if I got your meaning. If this is not what you are looking for, please clarify.