I am trying a java program to understand working of Future.
I wrote following program and it never ends. If I put a value that is less than 10 in Thread.sleep(), then it works but not for values >=10.
I understood the part that is causing problem is probably the future.get call.
However, on further analysis, what I tried was, to handle all the exceptions and not letting jvm handle them.
eg:
Now it terminated fine.
I did a further check and saw that if I throw ExecutionException and InterruptedException and handle TimeoutException it works fine again.
Here strange part is I have to compulsorily handle TimeoutException, else it will not work. I am not so sure why this strange behaviour persists.
I am using OpenJDK 15.
If anybody wants to try code snippet its here:
import java.util.concurrent.*;
public class FixedThreadPoolExecutorDemo2 {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
workWithFutureCallable(executorService);
executorService.shutdownNow();
}
private static void workWithFutureCallable(ExecutorService executorService) throws ExecutionException, InterruptedException, TimeoutException {
Future<Integer> myOtherFuture = executorService.submit(() -> {
try {
Thread.sleep(109);
} catch (InterruptedException e) {
}
return 1000;
});
System.out.println("myOtherFuture should be cancelled if running for more than specified time. ->" + myOtherFuture.get(10, TimeUnit.MILLISECONDS));
}
}
The TimeoutException is not being caught in main, so main is also terminating abruptly without calling shutdownNow. The main thread is terminated but the threads created by Executors are non-daemon by default, so the virtual machine is not shut down, the Executors thread(s) continue running.
Solution:
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
workWithFutureCallable(executorService);
} finally {
executorService.shutdownNow();
}
}
or
implement a ThreadFactory to create daemon threads and use it to get the service:
ExecutorService executorService = Executors.newFixedThreadPool(2, r -> {
var thread = new Thread(r);
thread.setDaemon(true);
return thread;
});
Even better, at least in production code, catch and handle the Exceptions (together with the finally block.)
Related
While solving the task, I've noticed a behavior I can not explain.
My task was to read from InputStream and interrupt that reading after a timeout. Even though lots of people say blocking read can not be interrupted, I've achieved that goal using CompletableFuture
public void startReader() {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> doRead(System.in));
future.get(5, TimeUnit.SECONDS);
}
private void doRead(InputStream in) {
try {
new BufferedReader(new InputStreamReader(in)).readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
But when I implement the same using Future, I can see TimeoutException been thrown into JVM, but I still can see that reading thread was not terminated and still running.
public void startReader() throws ExecutionException, InterruptedException, TimeoutException {
Future<?> future = Executors.newSingleThreadExecutor().submit(() -> doRead(System.in));
future.get(5, TimeUnit.SECONDS);
}
private void doRead(InputStream in) {
try {
new BufferedReader(new InputStreamReader(in)).readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
Why there is such a difference? I believe CompletableFuture does not make any magic
Neither of your code snippets will stop the "reading" thread when you reached the future.get(5, TimeUnit.SECONDS);. They will continue waiting for your input from System.in. If you want to stop it you should send an interrupt to that thread and hope the thread react on it. Or you can force kill the thread, obviously.
However, the CompletableFuture.runAsync() and Executors.newSingleThreadExecutor() calls use different threads, specially using different daemon flags (see What is a daemon thread in Java?). When you place a System.out.println(Thread.currentThread().isDaemon()); inside your doRead() method you will see that CompletableFuture.runAsync uses a daemon thread (so it doesn't block the JVM from terminating) where Executors.newSingleThreadExecutor() does not (and keeps the JVM alive).
When I do async call using ExecutorService, it returns Future Object. Based on the boolean value it returns, I have to log the status of the async call.
But when I try to call the method get method from the future object, it blocks the main thread execution.
Is it possible to unblock the main thread execution?
public class FutureExample {
static HystrixCommand<Boolean> hystrixCommand;
public FutureExample(HystrixCommand<Boolean> hystrixCommand){
FutureExample.hystrixCommand = hystrixCommand;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Boolean something = asyncCall();
if(something) {
System.out.println("Future task is done");
}
System.out.println("Don't wait for async call");
}
private static Boolean asyncCall() throws InterruptedException, ExecutionException {
Future<Boolean> response = hystrixCommand.queue(); // Aysnc Call to remote server
return response.get(); //this is blocking main thread
}
}
The good thing about futures is to be able to release threads until the answer arrives.
So I recommend you to use a Future implementation, like CompletableFuture:
final ExecutorService executorService = Executors.newFixedThreadPool(10);
CompletableFuture.supplyAsync(() -> {
try {
return hystrixCommand.queue();
} catch (Exception e) {
return false;
}
}, executorService);
This will work on another thread and when that future is over it will be done.
According to JavaDocs, get() method waits if necessary for the computation to complete, and then retrieves its result.
If you want to get the result once the task is completed, use isDone() function, which returns true if the task completed (normally, exceptionally, etc.). And invoke get() afterwards.
Also, you can use get(long timeout, TimeUnit unit) function to wait only for the given period of time. In this case the main thread will be "unblocked" automatically if either the time is out or the task has completed.
If you need to execute code in the main thread while the async task is running, you will need to redesign your asyncCall method to make it return a future instead.
An example:
private static Future<Boolean> asyncCall()
throws InterruptedException, ExecutionException {
return hystrixCommand.queue();
}
This way, the main method makes the call regarding when to block/wait:
public static void main(String[] args)
throws InterruptedException, ExecutionException {
Future<Boolean> something = asyncCall();
//do something while async call is running
//to check whether it's done running:
if(something.isDone()) {
System.out.println("Future task is done");
}
//when you're finally ready to wait:
System.out.println("Waiting for async call to finish");
Boolean result = something.get();
}
I meet a weired problem when using JUnit in multi-thread environment. The following code should fail, but it actually pass in eclipse.
public class ExampleTest extends TestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private volatile boolean isDone = false;
public void test() throws InterruptedException, ExecutionException {
executor.submit(new Runnable() {
#Override
public void run() {
try {
fail();
} finally {
isDone = true;
}
}
});
while (!isDone) {
Thread.sleep(1000);
}
}
}
And here'a another piece of code, here I use Future.get() to wait for thread stop, in this case it will fail.
public class ExampleTest extends TestCase {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private volatile boolean isDone = false;
public void test() throws InterruptedException, ExecutionException {
Future future=executor.submit(new Runnable() {
#Override
public void run() {
try {
fail();
} finally {
isDone = true;
}
}
});
future.get();
}
}
I googled it and found that JUnit can not handle Multiple-thread unit testing,but what's the differences between these two pieces of code ? Thanks
JUnit cannot see the exceptions that occur in threads other than the thread in which the tests are running. In the first case, through an exception occurs by calling fail, it occurs in a separate thread run by the executor. Hence it is not visible to JUnit and the test passes.
In the second case, the same exception happens in the separate thread run by the executor but the exception is effectively "reported back" to the test thread when you call future.get. This is because future.get throws an ExecutionException if the computation of the future failed due to any exception. JUnit is able to see this exception and hence the test fails.
As #abhin4v has pointed out, the exception in the new thread gets swallowed. You could try providing your own fail-method that syncronises with the top-level thread very much like in your example with get().
But there's no need to use Futures, just write to a shared variable indicating failure and use newThreadId.join(). Apart from that, I'm not aware of any other way of solving this in plain JUnit.
Take a look at http://www.youtube.com/watch?v=wDN_EYUvUq0 (starting at 17:09), it explain problems you can get with JUnit and threads.
I think, that in your case, get() throws a ExecutionException and that's why the second test fails. In the first testcase, jUnit doesn't see the exception.
There is also the interesting fact that Eclipse and IDEA can spawn a VM in their junit test runners and end up calling system.exit() on it. This means if you don't wait properly in the test (as in the case when you sleep above and hope the the task has completed), it can exit unexpectedly. Interesting, but not exactly what you were asking!
see this link for details...
In attempts of 100% code coverage, I came across a situation where I need to unit test block of code that catches an InterruptedException. How does one correctly unit test this? (JUnit 4 syntax please)
private final LinkedBlockingQueue<ExampleMessage> m_Queue;
public void addMessage(ExampleMessage hm) {
if( hm!=null){
try {
m_Queue.put(hm);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right before invoking addMessage(), call Thread.currentThread().interrupt(). This will set the "interrupt" status flag on the thread.
If the interrupted status is set when the call to put() is made on a LinkedBlockingQueue, an InterruptedException will be raised, even if no waiting is required for the put (the lock is un-contended).
By the way, some efforts to reach 100% coverage are counter-productive and can actually degrade the quality of code.
Use a mocking library like Easymock and inject a mock LinkedBlockingQueue
i.e.
#Test(expected=InterruptedException.class)
public void testInterruptedException() {
LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class);
ExampleMessage message = new ExampleMessage();
queue.put(message);
EasyMock.expectLastCall.andThrow(new InterruptedException());
replay(queue);
someObject.setQueue(queue);
someObject.addMessage(msg);
}
As stated above just make use Thread.currentThread().interrupt() if you caught InterruptedException and isn't going to rethrow it.
As for the unit testing. Test this way: Assertions.assertThat(Thread.interrupted()).isTrue();. It both checks that the thread was interrupted and clears the interruption flag so that it won't break other test, code coverage or anything below.
Another option is to delegate dealing with InterruptedException to Guava's Uninterruptibles, so you don't need to write and test your custom code for it:
import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
private final LinkedBlockingQueue<ExampleMessage> queue;
public void addMessage(ExampleMessage message) {
putUninterruptibly(queue, message);
}
One proper way could be customizing/injecting the ThreadFactory for the executorservice and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
Demo code part for the overwrited method "newThread" in ThreadFactory:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
},
5,
TimeUnit.SECONDS);
return thread;
}
}
Then you can use below to construct your executorservice instance:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in a way each thread will be interrupted once in executorservice.
The example code in the question may be testable by calling Thread.currentThread().interrupt(). However, besides the mentioned problems various methods reset the interrupted flag. An extensive list is for example here: https://stackoverflow.com/a/12339487/2952093. There may be other methods as well.
Assuming waiting implemented as follows should be tested:
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException ex) {
// Set the interrupt flag, this is best practice for library code
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
A call to Thread.sleep itself clears the interrupted flag, so it cannot be set in advance. It can be tested using its own test thread as follows:
AtomicBoolean threadInterrupted = new AtomicBoolean(false);
Runnable toBeInterrupted = () -> {
try {
methodUnderTest();
} catch (RuntimeException unused) {
// Expected exception
threadInterrupted.set(true);
}
};
// Execute the in an operation test thread
Thread testThread = new Thread(toBeInterrupted);
testThread.start();
// When the test thread is waiting, interrupt
while (!threadInterrupted.get()) {
if (testThread.getState() == Thread.State.TIMED_WAITING) {
testThread.interrupt();
}
}
// Assert that the interrupted state is re-set after catching the exception
// Must be happening before thread is joined, as this will clear the flag
assertThat(testThread.isInterrupted(), is(true));
testThread.join();
My code snippet:
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Task t = new Task(response,inputToPass,pTypes,unit.getInstance(),methodName,unit.getUnitKey());
Future<SCCallOutResponse> fut = executor.submit(t);
response = fut.get(unit.getTimeOut(),TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
// if the task is still running, a TimeOutException will occur while fut.get()
cat.error("Unit " + unit.getUnitKey() + " Timed Out");
response.setVote(SCCallOutConsts.TIMEOUT);
} catch (InterruptedException e) {
cat.error(e);
} catch (ExecutionException e) {
cat.error(e);
} finally {
executor.shutdown();
}
How should i handle the InterruptedException and ExecutionException in the code?
And in what cases, are these exceptions thrown?
ExecutionException and InterruptedException are two very different things.
ExecutionException wraps whatever exception the thread being executed threw, so if your thread was, for instance, doing some kind of IO that caused an IOException to get thrown, that would get wrapped in an ExecutionException and rethrown.
An InterruptedException is not a sign of anything having gone wrong. It is there to give you a way to let your threads know when it's time to stop so that they can finish up their current work and exit gracefully. Say I want my application to stop running, but I don't want my threads to drop what they're doing in the middle of something (which is what would happen if I made them daemon threads). So when the application is being shutdown, my code calls the interrupt method on these threads, which sets the interrupt flag on them, and the next time those threads are waiting or sleeping they check the interrupt flag and throw an InterruptedException, which I can use to bail out of whatever infinite-loop processing/sleeping logic the threads are engaged in. (And if the thread doesn't wait or sleep, it can just check the interrupt flag periodically.) So it is an instance of an exception being used to change the logical flow. The only reason you would log it at all is in an example program to show you what's happening, or if you're debugging a problem where interrupt logic is not working correctly.
InterruptedException will be thrown if interrupt is called on the waiting thread before the computation has completed.
ExecutionException will be thrown if the computation involved (Task in this case) throws an exception itself.
How you want to handle this will entirely depend on your application.
EDIT: Here's a demonstration of being interrupted:
import java.util.concurrent.*;
public class Test
{
public static void main(String[] args) throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(new SlowCallable());
executor.submit(new Interruptor(Thread.currentThread()));
try
{
System.out.println(future.get());
}
catch (InterruptedException e)
{
System.out.println("I was interrupted");
}
}
private static class Interruptor implements Callable<String>
{
private final Thread threadToInterrupt;
Interruptor(Thread threadToInterrupt)
{
this.threadToInterrupt = threadToInterrupt;
}
public String call() throws Exception
{
Thread.sleep(2000);
threadToInterrupt.interrupt();
return "interrupted other thread";
}
}
private static class SlowCallable implements Callable<String>
{
public String call() throws Exception
{
Thread.sleep(5000);
return "finished";
}
}
}
Sample code to return three types of Exceptions.
import java.util.concurrent.*;
import java.util.*;
public class ExceptionDemo{
public static void main(String args[]){
int poolSize=1;
int maxPoolSize=1;
int queueSize=30;
long aliveTive=60;
ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
ThreadPoolExecutor executor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
TimeUnit.MILLISECONDS,queue);
List<Future> futures = new ArrayList<Future>();
for ( int i=0; i < 5; i++){
futures.add(executor.submit(new RunnableEx()));
}
for ( Iterator it = futures.iterator(); it.hasNext();){
try {
Future f = (Future)it.next();
f.get(4000,TimeUnit.MILLISECONDS);
}catch(TimeoutException terr){
System.out.println("Timeout exception");
terr.printStackTrace();
}
catch(InterruptedException ierr){
System.out.println("Interrupted exception:");
ierr.printStackTrace();
}catch(ExecutionException err){
System.out.println("Exeuction exception:");
err.printStackTrace();
Thread.currentThread().interrupt();
}
}
executor.shutdown();
}
}
class RunnableEx implements Runnable{
public void run() {
// code in here
System.out.println("Thread name:"+Thread.currentThread().getName());
try{
Random r = new Random();
if (r.nextInt(2) == 1){
Thread.sleep(2000);
}else{
Thread.sleep(4000);
}
System.out.println("eee:"+1/0);
}catch(InterruptedException irr){
irr.printStackTrace();
}
}
}
output:
Thread name:pool-1-thread-1
Timeout exception
Thread name:pool-1-thread-1
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Exeuction exception:
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:202)
at ExceptionDemo.main(ExceptionDemo.java:20)
Caused by: java.lang.ArithmeticException: / by zero
at RunnableEx.run(ExceptionDemo.java:49)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Interrupted exception:
java.lang.InterruptedException
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
at java.util.concurrent.FutureTask.get(FutureTask.java:199)
at ExceptionDemo.main(ExceptionDemo.java:20)
Timeout exception
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
Thread name:pool-1-thread-1
at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Timeout exception
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at ExceptionDemo.main(ExceptionDemo.java:20)
TimeoutException : Exception thrown when a blocking operation times out.
In above example, some tasks are taking more time (due to 4 seconds sleep) and blocking operation of get() on Future
Either increase the time-out or optimize Runnable task.
ExecutionException: Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception => The computation threw an exception
In above example, this Exception is simulated through ArithmeticException: / by zero
Generally, you should catch it fix the root cause if it is trivial as quoted in the example.
InterruptedException: Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity.
In above example, this Exception is simulated by interrupting current Thread during ExecutionException.
Generally, you should catch it don't act on it.