How to interrupt a function call in Java - java

I am trying to use a Third Party Internal Library which is processing a given request. Unfortunately it is synchronous in nature. Also I have no control on the code for the same. Basically it is a function call. This function seems to a bit erratic in behavior. Sometimes this function takes 10 ms to complete processing and sometimes it takes up to 300 secs to process the request.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs. I can live with not having the results and continue processing, but cannot tolerate a 3 min delay.
PS: This function internally sends an update to another system using JMS and waits for that system to respond and sends apart from some other calculations.

Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs.
This is not possible. InterruptException only gets thrown by specific methods. You can certainly call thread.stop() but this is deprecated and not recommended for a number of reasons.
A better alternative would be for your code to wait for the response for a certain amount of time and just abandon the call if doesn't work. For example, you could submit a Callable to a thread pool that actually makes the call to the "Third Party Internal Library". Then your main code would do a future.get(...) with a specific timeout.
// allows 5 JMS calls concurrently, change as necessary or used newCachedThreadPool()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
...
// submit the call to be made in the background by thread-pool
Future<Response> future = threadPool.submit(new Callable<Response>() {
public Response call() {
// this damn call can take 3 to 3000ms to complete dammit
return thirdPartyInternalLibrary.makeJmsRequest();
}
});
// wait for some max amount of time
Response response = null;
try {
response = future.get(TimeUnit.MILLISECONDS, 100);
} catch (TimeoutException te) {
// log that it timed out and continue or throw an exception
}
The problem with this method is that you might spawn a whole bunch of threads waiting for the library to respond to the remote JMS query that you would not have a lot of control over.
No easy solution.

This will throw a TimeoutException if the lambda doesn't finish in the time allotted:
CompletableFuture.supplyAsync(() -> yourCall()).get(1, TimeUnit.SECONDS)

Being that this is 3rd party you cannot modify the code. As such you will need to do two things
Launch the execution in a new thread.
Wait for execution in current thread, with timeout.
One possible way would be to use a Semaphore.
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// do work
semaphore.release();
}
});
t.start();
try {
semaphore.tryAcquire(1, TimeUnit.SECONDS); // Whatever your timeout is
} catch (InterruptedException e) {
// handle cleanup
}
The above method is gross, I would suggest instead updateing your desing to use a dedicated worker queue or RxJava with a timeout if possible.

Related

Moving a task to a separate thread, avoid duplication while task running & proper use of Executors + Future

We have a glue component between legacy code and current code. Essentially the whole legacy application is single threaded and has horrible issues where a ui refresh for a single instruction can happen 5 to 8 times.
I want to publish an async message after the first update request happens +2 seconds.
Let's not get stuck on the why, this is not what I want to really do, but I have to understand how to at least do this so I can implement a real solution.
Runnable task = () -> {
try {
TimeUnit.SECONDS.sleep(2);
messageBus.publishAsynch(new LegacyUiUpdateEvent());
} catch (InterruptedException e) {
// TODO Log something
Thread.currentThread().interrupt();
}
};
#Override
public void update(Observable arg0, Object arg1) {
ExecutorService executor = Executors.newSingleThreadExecutor();
if (futureTask == null || futureTask.isDone()) {
futureTask = executor.submit(task);
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
executor.shutdownNow();
} catch (InterruptedException e) {
// TODO Log something
Thread.currentThread().interrupt();
}
}
}
The theory is: If future task doesn't exist, we create it, once it's there, if it's not done (because this is false legacy update 4/x where x ∈ [5,12] and the sleep is still in effect) then we completely skip and don't create a new executor.
The problem is that, from what I can tell, the executor.submit(task) does not in fact happen on a new tread. Like I said the legacy app is single threaded, and after I increased the sleep to 15s it was blindingly obvious that it was sending the whole current thread to sleep.
How would I put my taks on a completely new thread (using the concurrency library) and avoiding doing the task multiple times, even though the update method is being called way way too many times (and that is 100% out of my control). I think the future.isDone() thing works, but not 100%
if you are on Java 8 or higher, this is a better thing to do
CompletableFuture.runAsync(task);
because this will be executed on the Fork-join thread pool, that is managed by the JVM and you will not concern yourself by creating it nor shutting it down. and of course this will run asynchronously which match your requirements .
executor.submit() does start the task in a new thread, but right after executor.awaitTermination(10, TimeUnit.SECONDS); is waiting in the current thread for the task to be completed. There's no need to wait in the current thread, but there does need to be a way to determine if the task is already running.
The messy part is creating the ExecutorService each time - there's no need to recreate it each time. It can be an instance variable of the class and re-used. Ideally, it would be injected through a constructor so the class which created it can shut it down if that's really needed.
private final ExecutorService executor = Executors.newSingleThreadExecutor(); // or injected through constructor
private Future<?> futureTask;
#Override
public void update(Observable arg0, Object arg1) {
if (futureTask == null || futureTask.isDone()) {
futureTask = executor.submit(task);
}
}

Async API giving worse performance

Interesting, I would think have 255 concurrent users, an async API would have better performance. Here are 2 of my endpoints in my Spring server:
#RequestMapping("/async")
public CompletableFuture<String> g(){
CompletableFuture<String> f = new CompletableFuture<>();
f.runAsync(() -> {
try {
Thread.sleep(500);
f.complete("Finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return f;
}
#RequestMapping("/sync")
public String h() throws InterruptedException {
Thread.sleep(500);
return "Finished";
}
In the /async it runs it on a different thread. I am using Siege for load testing as follows:
siege http://localhost:8080/sync --concurrent=255 --time=10S > /dev/null
For the async endpoint, I got a transaction number of 27 hits
For the sync endpoint, I got a transaction number of 1531 hits
So why is this? Why isnt the async endpoint able to handle more transactions?
Because the async endpoint is using a shared (the small ForkJoinPool.commonPool()) threadpool to execute the sleeps, whereas the sync endpoint uses the larger threadpool of the application server. Since the common pool is so small, you're running maybe 4-8 operations (well, if you call sleeping an operation) at a time, while others are waiting for their turn to even get in the pool. You can use a bigger pool with CompletableFuture.runAsync(Runnable, Executor) (you're also calling the method wrong, it's a static method that returns a CompletableFuture).
Async isn't a magical "make things faster" technique. Your example is flawed as all the requests take 500ms and you're only adding overhead in the async one.

How to be sure threads are cleaned up

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();

Java Multithreaded - Better way to cancel Future task with database and http connections?

I am having difficulty trying to correctly program my application in the way I want it to behave.
Currently, my application (as a Java Servlet) will query the database for a list of items to process. For every item in the list, it will submit an HTTP Post request. I am trying to create a way where I can stop this processing (and even terminate the HTTP Post request in progress) if the user requests. There can be simultaneous threads that are separately processing different queries. Right now, I will stop processing in all threads.
My current attempt involves implementing the database query and HTTP Post in a Callable class. Then I submit the Callable class via the Executor Service to get a Future object.
However, in order properly to stop the processing, I need to abort the HTTP Post and close the database's Connection, Statement and ResultSet - because the Future.cancel() will not do this for me. How can I do this when I call cancel() on the Future object? Do I have to store a List of Arrays that contains the Future object, HttpPost, Connection, Statement, and ResultSet? This seems overkill - surely there must be a better way?
Here is some code I have right now that only aborts the HttpPost (and not any database objects).
private static final ExecutorService pool = Executors.newFixedThreadPool(10);
public static Future<HttpClient> upload(final String url) {
CallableTask ctask = new CallableTask();
ctask.setFile(largeFile);
ctask.setUrl(url);
Future<HttpClient> f = pool.submit(ctask); //This will create an HttpPost that posts 'largefile' to the 'url'
linklist.add(new tuple<Future<HttpClient>, HttpPost>(f, ctask.getPost())); //storing the objects for when I cancel later
return f;
}
//This method cancels all running Future tasks and aborts any POSTs in progress
public static void cancelAll() {
System.out.println("Checking status...");
for (tuple<Future<HttpClient>, HttpPost> t : linklist) {
Future<HttpClient> f = t.getFuture();
HttpPost post = t.getPost();
if (f.isDone()) {
System.out.println("Task is done!");
} else {
if (f.isCancelled()) {
System.out.println("Task was cancelled!");
} else {
while (!f.isDone()) {
f.cancel(true);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("!Aborting Post!");
try {
post.abort();
} catch (Exception ex) {
System.out.println("Aborted Post, swallowing exception: ");
ex.printStackTrace();
}
}
}
}
}
}
Is there an easier way or a better design? Right now I terminate all processing threads - in the future, I would like to terminate individual threads.
I think keeping a list of all the resources to be closed is not the best approach. In your current code, it seems that the HTTP request is initiated by the CallableTask but the closing is done by somebody else. Closing resources is the responsibility of the one who opened it, in my opinion.
I would let CallableTask to initiate the HTTP request, connect to database and do it's stuff and, when it is finished or aborted, it should close everything it opened. This way you have to keep track only the Future instances representing your currently running tasks.
I think your approach is correct. You would need to handle the rollback yourself when you are canceling the thread
cancel() just calls interrupt() for already executing thread. Have a look here
http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html:
As it says
An interrupt is an indication to a thread that it should stop what it
is doing and do something else. It's up to the programmer to decide
exactly how a thread responds to an interrupt, but it is very common
for the thread to terminate.
Interrupted thread would throw InterruptedException
when a thread is waiting, sleeping, or otherwise paused for a long
time and another thread interrupts it using the interrupt() method in
class Thread.
So you need to explicitly code for scenarios such as you mentioned in executing thread where there is a possible interruption.

two serial tasks slower than parallel

Hi I have a webapp - and in one method I need to encrypt part of data from request and store them on disk and return response.
Response is in no way related to encryption.
The encryption is quite time demanding however. How to make threads or so properly in this problem?
I tried something like
Thread thread ...
thread.start();
or
JobDetail job = encryptionScheduler.getJobDetail(jobDetail.getName(), jobDetail.getGroup());
encryptionScheduler.scheduleJob(jobDetail,TriggerUtils.makeImmediateTrigger("encryptionTrigger",1,1)
I tried servlet where before encryption I close the outpuStream.
or: Executors.newFixedThreadPool(1);
But whatever I tried a client has to wait longer.
btw: why is that so? Can it be faster?
I haven't tried to start thread after context initalization and wait somehow for method needing encryption.
how to speed up this?
thank you
--------------EDIT:
//I use axis 1.4, where I have Handler, which in invoke method encrypt a value:
try {
LogFile logFile = new LogFile(strategy,nodeValue,path, new Date());
LogQueue.queue.add(logFile);
}
catch (Exception e) {
log.error(e.getMessage(),e);
}
EExecutor.executorService.execute(new Runnable() {
public void run() {
try {
LogFile poll = LogQueue.queue.poll();
String strategy = poll.getStrategy();
String value = poll.getNodeValue();
value = encrypt(strategy,value);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(poll.getPath(), true )),"UTF-8"));
writer.print(value);
writer.close();
}catch (IOException e ) {
log.error(e.getMessage(),e);
}
}
});
} catch (Throwable e ) {
log.error(e.getMessage(),e);
}
//besides I have executor service
public class EExecutor { public static ExecutorService executorService = Executors.newCachedThreadPool();}
//and what's really interesting.. when I move encryption from this handler away into another handler which is called
last when I send response! It's faster. But when I leave it in one of the first handlers when I receive request. It's even slower without using threads/servlet etc.
Threads only help you if parts of your task can be done in parallel. It sounds like you're waiting for the encryption to finish before returning the result. If it's necessary for you to do that (e.g., because the encrypted data is the result) then doing the encryption on a separate thread won't help you here---all it will do is introduce the overhead of creating and switching to a different thread.
Edit: If you're starting a new thread for each encryption you do, then that might be part of your problem. Creating new threads is relatively expensive. A better way is to use an ExecutorService with an unbounded queue. If you don't care about the order in which the encryption step happens (i.e., if it's ok that the encryption which started due to a request at time t finishes later than one which started at time t', and t < t'), then you can let the ExecutorService have more than a single thread. That will give you both greater concurrency and save you the overhead of recreating threads all the time, since an ExecutorService pools and reuses threads.
The proper way to do something like this is to have a message queue, such as the standard J2EE JMS.
In a message queue, you have one software component whose job it is to receive messages (such as requests to encrypt some resource, as in your case), and make the request "durable" in a transactional way. Then some independent process polls the message queue for new messages, takes action on them, and transactionally marks the messages as received.

Categories

Resources