I am trying to implement a code where I want to call a function from JNI which should have a timeout. If it exceeds the timeout, I want to terminate the native task. I am posting a piece of code to show as an example.
void myFunction(timeOutInSeconds)
{
if(timeOutInSeconds > 0)
{
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Integer> task = new Callable<Integer>() {
public Integer call() {
System.out.println("Calling JNI Task");
JNI_Task();
System.out.println("Finished JNI Task");
return 0;
}
};
Future<Integer> future = executor.submit(task);
try
{
#SuppressWarnings("unused")
Integer result = future.get(timeOutInSeconds, TimeUnit.SECONDS);
}
catch (TimeoutException ex)
{
// handle the timeout
kill_task_in_JNI();
// future.cancel(true);
return TIMEOUT;
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
}
finally
{
// future.cancel(true);
executor.shutdown();
}
}
else
JNI_Task();
}
There are several questions -
Where should I exactly put future.cancel(). There are 2 locations which are commented.
If I run this function with timeOutInSeconds = 0, it runs perfectly.
However Irrespective of the value of timeOutInSeconds, the task gets stuck up and
the JNI task does not get called. I check this by putting printf's in the JNI
code. The task takes 1 second to execute and I gave 30 seconds, 5 minutes etc. still it
is stuck up.
Is there any problem with such approach?
You can (and in this case should) call future.cancel() only in the finally block. http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html.
About the 2nd question, its not clear for me if the problem also occur when timeOutInSeconds=0. Is this the case? Can you provide the content of the JNI_TASK() method?
Related
I have code that should execute reasonably fast but occasionally may take long time to execute and produce a result. I'd like to limit the duration of that operation and abort it if it runs longer than a given time limit. I'd like the code to look like
Supplier<T> longRunningFoo = () -> {...}; // this may take a while to run
LongOpRunner runner = new LongOpRunner(longRunningFoo); // <-- some wrapper that limits operation duration
try {
T result = runner.call(10000 /* ms */); // abort after 10000 milliseconds
} catch (LongOpTimeout e) {
// handle timeout exception when "foo" gets aborted
}
Before I start writing my own I am interested to see if there are existing libraries that provide this capability.
You can use Java provided built in Future where it provides the facility for timeout. See below the small code snippet.
ExecutorService ex = Executors.newSingleThreadExecutor();
Future<?> future = ex.submit(new Runnable() {
public void run() {
try {
//Do some long running operations
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed operation");
}
});
Object someObject = future.get(10, TimeUnit.SECONDS);
You can also refer below the link for further reference.
You can use ExecutorService.submit(Callable task) and then call Future.get(long timeout, TimeUnit unit) on the result.
This question already has answers here:
ExecutorService that interrupts tasks after a timeout
(11 answers)
Closed 7 years ago.
This is just an example to explain my problem...
I am using ExecutorService with 20 active threads and 75K max queued items...
In my case, a normal task should not take more than 10 seconds, if it takes more time that means there's some problem with the task.
If all the threads are hung due to problematic tasks my RejectionHandler would restart the entire service.
I have two questions here:
I do not like the idea of restarting the service, instead if there's
way to detect hanging thread and we could just restart that hung
thread that would be great. I have gone through couple of articles to handle hung threads with ThreadManager but have not found anything
with ExecutorService.
I am very much fascinated about the Executors.newCachedThredPool()
because on peak days we are heavily loaded with incoming tasks, and
on other days they are very few. Any suggestions would be greatly
appreciated.
public class HangingThreadTest {
// ExecutorService executorService = Executors.newCachedThreadPool()
private static ExecutorService executorService = new ThreadPoolExecutor(10,
20, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(75000));
public static void main(String... arg0) {
for (int i = 0; i < 50000; i++) {
executorService.submit(new Task());
}
}
}
/**
* Task to be completed
*/
class Task implements Runnable {
private static int count = 0;
#Override
public void run() {
count++;
if (count%5 == 0) {
try {
System.out.println("Hanging Thread task that needs to be reprocessed: "
+ Thread.currentThread().getName()+" count: "+count);
Thread.sleep(11000);
} catch (InterruptedException e) {
// Do something
}
}
else{
System.out.println("Normal Thread: "
+ Thread.currentThread().getName()+" count: "+count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//Do something
}
}
}
}
There is no build-in mechanism in Executors framework that would help terminate a thread if it has been running for more than a threshold value.
But we can achieve this with some extra code as below:
Get the Future object returned by the executorService.submit(...);.
Future future = executorService.submit(new Task());
Call the get method on this future object to and make it wait only for threshold interval for task completion. Below, an example that is waits for only 2 secs.
try {
f.get(2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
f.cancel(true);
} catch (Exception e) {}
The above code waits for 2 seconds for task completion it throws a TimeoutException if it doesn't get completed during that time. Subsequently we can call cancel method on the future object. This results in setting the interrupt flag in the thread that is executing the task.
Now the final change is, in the Task class code we need to check at necessary points (application dependent), whether the interrupt flag has been set to true using isInterrupted() method of Thread class. If interrupted==true, we can do the necessary clean up and return from the run method immediately. The critical piece here is to identify the necessary points in your Task class where you want to check for this interrupted flag.
This makes the thread available for processing next task.
You may have a look at this article, it was very helpful for me before when I was facing the same problem : Java Hanging Thread Detection
I think mistakenly guys compared take() vs poll(), but I found that it is reasonable to compare take() vs poll(time, unit) as both provided by BlockingQueue and both are blocking tell queue not Empty "and in case or poll or time-out", OK lets start comparing, usually I'm using take() for BlockingQueue but I was facing issues about:
handling interrupt inside loop.
waiting till be interrupted from outside.
how to stop looping on queue "using Kill-Bill or interrupt thread"
specially when work with Java 8 streams, then I got idea about I need to stop retrieving data from queue and close it in better way, so I thought to make waiting for sometime after that I can stop retrieve data then I found poll(time, unit) and it will fit for this idea check code below:
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Integer> q = new LinkedBlockingQueue<Integer>();
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
IntStream.range(0, 1000).boxed().forEach(i -> {
try {
q.put(i);
} catch (InterruptedException e) {
currentThread().interrupt();
throw new RuntimeException(e);
}
});
});
....
// Take
Future fTake = executor.submit(() -> {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println(q.take());
}
} catch (InterruptedException e) {
currentThread().interrupt();
throw new RuntimeException(e);
}
});
//to stop it I have to do below code "Expecting that execution will take 1 sec"
executor.shutdown();
sleep(1000);
fTake.cancel(true);
....
// poll there is no need to expect time till processing will be done
Future fPoll = executor.submit(() -> {
try {
Integer i;
while ((i = q.poll(100, TimeUnit.MILLISECONDS)) != null)
System.out.println(i);
} catch (InterruptedException e) {
currentThread().interrupt();
throw new RuntimeException(e);
}
});
executor.shutdown();
}
I think the poll code is more clean and there is no need to depend on interrupt and also no need to estimate execution time or make code to determined when to interrupt thread, what do you think?
Note 1: I'm sure that 2nd solution also have drawbacks like not getting data till time-out but I think you are going to know what is suitable time-out for your case.
Note 2: if use case requires waiting for ever and producer is low frequency provide data, I think take solution is better.
I am struggling with a use case where one of the tasks submitted to invokeall() throws CancellationException forcing program NOT to terminate. How can make sure this program will terminate properly in case of CancellationException ?
How I am finding out my program not terminated clean? I am using netbeans and shows progress bar at bottom right if program doesn't terminate.
Here is code:
int poolSize = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
Set<Callable<Object>> tasksSet = new HashSet<>();
tasksSet.add(new Task1());
tasksSet.add(new Task2());
tasksSet.add(new Task3());
List<Future<TrendLineStatisticsVO>> resultSet = pool.invokeAll(tasksSet, 1, TimeUnit.MINUTES);
for (Future<Object> future : resultSet) {
Object result;
try {
result = future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (TimeoutException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
pool.shutdown();
And Task1 code:
public class Task1 implements Callable<Object> {
#Override
public Object call() throws Exception {
//This for sure takes days to complete, so should through Cancellation exception because timeout on invokeall set to 1 minute
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
val += i;
}
return "Sucessfull Task1 object...";
}
}
Task2 and Task3 code also same except these two classes use Integer.MAX_VALUE in for loop check.
There are two issues:
1)
Per the Javadoc:
tasks that have not completed are cancelled.
So you will have to code your Task to be responsive to interruption. What is happening in the background is similar to future.cancel(true) if the tasks don't complete in the time specified, the true in the argument says to interrupt() the thread running the task. Like I mentioned, your tasks will have to look out for interruption. Something similar to:
#Override
public Object call() throws Exception {
//This for sure takes days to complete, so should through Cancellation exception because timeout on invokeall set to 1 minute
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
if(Thread.interruped()){
throw new RuntimeException("Did not complete in time: " + i);
}
val += i;
}
return "Sucessfull Task1 object...";
}
How I am finding out my program not terminated clean? I am using netbeans and shows progress bar at bottom right if program doesn't terminate.
Without my update above the program will never end as the thread pool is still running. shutdown will do nothing as the tasks haven't completed (event with cancel).
2)
A task that is cancelled, by definition, did not complete (or even start) so invoking get on the Future will fail quickly. You could ask the future if it's cancelled Future#isCancelled.
Background (can skip to question below...)
Currently working with a lego Mindstorm robot and the icommand API (http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/index.html).
Having some trouble with one of the motor control methods. The methods rotates the motor by a given angle:
Motor.A.rotateTo(target);
This function will not return until the motor has completed the movement. This is fine, but sometimes the motor fails to stop and will continue indefinitely thus stopping the program.
Question
Is there anyway I can make so the program waits for up n seconds for the method Motor.A.rotateTo(target); to return. And then if it has not returned in that time, then call the method again. (If that could be looped until it is successful that would be even better.)
Thanks for reading, any help would be much appreciated.
Regards,
Joe
edit: corrected from Motor.A.rotate(target); to Motor.A.rotateTo(target);
You can use ExecutorService or other threading solution to run rotate in a separate thread and wait for results. Here is a complete program that also retries given number of times:
public static void main(String[] args) throws TimeoutException {
final ExecutorService pool = Executors.newFixedThreadPool(10);
runWithRetry(pool, 5); //run here
}
public static void runWithRetry(final ExecutorService pool, final int retries) throws TimeoutException {
final Future<?> result = pool.submit(new Runnable() {
#Override
public void run() {
Motor.A.rotate(angle);
}
});
try {
result.get(1, TimeUnit.SECONDS); //wait here
} catch (InterruptedException e) {
throw new RuntimeException(e.getCause());
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
} catch (TimeoutException e) {
if (retries > 1) {
runWithRetry(pool, retries - 1); //retry here
} else {
throw e;
}
}
}
What about Motor#rotate(long count, boolean returnNow) ? You can then call stop() if you want the motor to stop after a specific time.
Motor.A.rotate(150, true);
Thread.sleep(3000);
Motor.A.stop();
What about something along the lines of :
int desiredPosition = Motor.A.getTachoCount() + ANGLE_TO_TURN;
long timeout = System.currentTimeMillis + MAX_TIME_OUT;
Motor.A.forward();
while (timeout>System.currentTimeMillis && desiredPosition>Motor.A.getTachoCount()); //wait for the motor to reach the desired angle or the timeout to occur
Motor.A.stop();