How to Call Some Blocking Method with a Timeout in Java

How do I call some blocking method with a timeout in Java?

You could use an Executor:

ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
return something.blockingMethod();
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
// handle the timeout
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
} finally {
future.cancel(true); // may or may not desire this
}

If the future.get doesn't return in 5 seconds, it throws a TimeoutException. The timeout can be configured in seconds, minutes, milliseconds or any unit available as a constant in TimeUnit.

See the JavaDoc for more detail.

Java: set timeout on a certain block of code?

Yes, but its generally a very bad idea to force another thread to interrupt on a random line of code. You would only do this if you intend to shutdown the process.

What you can do is to use Thread.interrupt() for a task after a certain amount of time. However, unless the code checks for this it won't work. An ExecutorService can make this easier with Future.cancel(true)

Its much better for the code to time itself and stop when it needs to.

calling a blocking method call with timeout in java

You have everything set up to do that in the code you provide. Just replace

// handle other exceptions

with your exception handling.

If you need to get your specific Exception you get it with:

Throwable t = e.getCause();

And to differentiate between your Exceptions you can do like this:

if (t instanceof MyException1) {
...
} else if (t instanceof MyException2) {
...
...

How to implement synchronous method timeouts in Java?

You should use ExecutorService to do that

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Callable() {

public String call() throws Exception {
//do operations you want
return "OK";
}
});
try {
System.out.println(future.get(2, TimeUnit.SECONDS)); //timeout is in 2 seconds
} catch (TimeoutException e) {
System.err.println("Timeout");
}
executor.shutdownNow();

How do I timeout a method after fixed time in java using concurrency executor future?

The first problem is in this part of code:

catch(Exception e)
{
}

When you invoke future.cancel(true); your thread is being interrupted with Thread.interrupt()
Which means that when a thread is sleeping, it gets awoken and throws InterruptedException which is caught by the catch block and ignored. To fix this problem you have to handle this exception:

catch(InterruptedException e) {
break; //breaking from the loop
}
catch(Exception e)
{
}

The second problem: Thread.interrupt() may be invoked while the thread is not sleeping. In this case InterruptedException is not thrown. Instead, the interrupted flag of the thread is raised. What you have to do is to check for this flag from time to time, and if it's raised, handle interruption. The basic code for it would look like:

try {
if (Thread.currentThread().isInterrupted()) {
break;
}
TimeUnit.SECONDS.sleep(1);
}

...

// rest of the code

UPDATE:
Here's the full code of Callable:

Callable<Object> task = new Callable<Object>() {
public Object call() {
int i=1;
while(i<100)
{
System.out.println("i: "+ i++);
try {
if (Thread.currentThread().isInterrupted()) {
break; //breaking from the while loop
}
TimeUnit.SECONDS.sleep(1);
} catch(InterruptedException e) {
break; //breaking from the while loop
} catch(Exception e)
{
}
}
return null;
}
};

How do I timeout a blocking call inside an EJB?

how can I enforce a timeout?

The ejb3.1 specification provides the possibility to set a timeout using @AccessTimeout annotation that applies for serialized client calls that have to wait when an Session Bean instance
is busy executing a previous request.
Clearly (and explicity described in the specification) this applies to StateFul and Singleton session bean, although it could be implemented for Stateless in the case the bean pool run out of available instances.
Notice, once the client-invoked business method is in progress this timeout no applies.

Other possibility that is not part of the specification but, is supported by several servers (see JBoss example) is to define a timeout at the remote client side. If the client invocation
takes longer than the configured timeout, the client will be informed, however, the server execution will not be interrupted which it is not good enough.

Set a transaction timeout neither is a good option because there is no guarantee the thread that executes the business logic will be interrupted when the transaction timeout expires.

I would normally use a Executor to solve this problem but, from what I understand, one shouldn't spawn threads from within an EJB..

Instead you could use ManagedExecutorService class that is an Executor extension suitable to use within a EJB Container.

Aditionally, to implement asynchronous call within an EJB, take a look at @Asynchronous annotation, which provides a high level abstraction to solve the multithreding issue you are facing.
Cancel() method from Future class, allows you to interrup a thread's execution if you consider that the process has taken too long.



Related Topics



Leave a reply



Submit