I run a jar with an embedded Jetty. From time to time it happens that one request get stuck in some endless loop. Obviously fixing the endless-loop would be the best option. However, this is currently not possible.
So I am looking for an option, that checks if a request exists for more than e.g. 5 minutes, and kills the corresponding thread.
I tried the typical Jetty options:
maxIdleTime
soLingerTime
stopTimeout
None of them worked as expected. Is there another option to consider?
Do you access to the code that kicks of the code which takes too long to complete? If so you can use callable and an Executor to achieve this yourself, below is a unit test with an example:
#Test
public void timerTest() throws Exception
{
//create an executor
ExecutorService executor = Executors.newFixedThreadPool(10);
//some code to run
Callable callable = () -> {
Thread.sleep(10000); //sleep for 10 seconds
return 123;
};
//run the callable code
Future<Integer> future = (Future<Integer>) executor.submit(callable);
Integer value = future.get(5000, TimeUnit.MILLISECONDS); //this will timeout after 5 seconds
//kill the thread
future.cancel(true);
}
Related
I have a JSP application in which a webpage calls five methods one by one (all of them fetch data from different sources) and display charts based on data.
To load the webpage fastly, I planned to call all the five methods in parallel with the help of FixedThreadPool Executor.
Should I shut down my executor once I get the result from all five methods? Shutting down the executor is a bad idea according to me, since if someone opens the webpage a second time it will require the executor to initialize again in order to call the five methods parallelly.
However, I'm not sure about the consequences of leaving the executor open so not sure how to proceed.
Leaving it open is the normal way to use a thread pool. That's the whole point of thread pools: It's to prevent your application from having to create and then destroy however many new threads every time it needs to load a page. Instead, it can just use the same threads again and again.
In chapter 7 of "Java Concurrency in Practice" there is an example just like this, where a so called one-shot execution service is proposed:
If a method needs to process a batch of tasks and does not return until all the
tasks are finished, it can simplify service lifecycle management by using a private
Executor whose lifetime is bounded by that method.
Its code example:
boolean checkMail(Set<String> hosts, long timeout, TimeUnit unit)
throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
final AtomicBoolean hasNewMail = new AtomicBoolean(false);
try {
for (final String host : hosts)
exec.execute(new Runnable() {
public void run() {
if (checkMail(host))
hasNewMail.set(true);
}
});
} finally {
exec.shutdown();
exec.awaitTermination(timeout, unit);
}
return hasNewMail.get();
}
I'd suggest simplifying your code using this approach.
I'm using an external lib (Generex) in my project, and one constructor may take a very long time to execute, so I'd like to have a timeout (let's say 50 ms), and be able to know if the timeout has been reached or not.
So I was thinking at using a dedicated thread, and wrote the following code:
#Test
public void isComputable() throws InterruptedException {
for (int i=0; i<10;i++)
System.out.println(check());
Thread.sleep(300000);
}
private static boolean check() {
final Thread stuffToDo = new Thread(() -> {while(true){}});
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(stuffToDo);
executor.shutdown();
try {
future.get(50, TimeUnit.MILLISECONDS);
}
catch (InterruptedException | ExecutionException | TimeoutException ie) {
stuffToDo.interrupt();
stuffToDo.stop();
return false;
}
if (!executor.isTerminated())
executor.shutdownNow();
return true;
}
I replaced the call to the external lib with a while(true) loop, yet it is important to note that, in my case, I cannot use a loop to check if the thread was interrupted.
When executing this code, I've got well the answer after 50 ms for each call, yet the thread is not destroyed, and there is a high CPU usage, as we can see with JProfiler (note that the loop in the test over i is just to have a nicer chart):
Does anyone have any idea on how to solve this issue please?
Note: I know that I should not use the deprecated stop method, I just tried everything I know to kill the thread.
You either have to check for an interrupt regularly in your code callex or you have to run the code in another process. These are the only ways you can either interrupt or kill the process running the code.
I suggest taking a stack trace of the long running thread to help fix it in the future.
An idea I am trying to implement is the following.
I have 1000 urls to download data from to use it for post processing (say, calculating some statistics).
I don't really need all of the downloads to finish successfully, but as many as possible.
I assume that some of the locations might be unavailable, either responding nothing valuable (e.g., HTTP 503) or taking more that TO=10 seconds of time to process a request.
I have T=5 threads to process the urls in parallel, giving the equal timeout TO to each.
As soon as one completes (what I expect to happen far earlier that TO exceeds) I aggregate some statistics (what is a very fast operation) and start the next download (if any).
The solution I have come up so far with is
ExecutorService executorService = Executors.newFixedThreadPool(T);
ExecutorCompletionService<MyResult> completionService = new ExecutorCompletionService<>(executorService);
urls.forEach(url -> {
Callable<MyResult> callable = () -> new MyResult(url);
completionService.submit(callable);
});
for (int i = 0; i < urls.size(); i++) {
Future<MyResult> resultFuture = completionService.poll(TO, TimeUnit.SECONDS);
if (resultFuture == null)
continue;
MyResult myResult = resultFuture.get();
myAggregate(myResult.getRate());
}
It looks like somewhat I am trying to achieve. But it for instance neither gives every download the same timeout nor cancels the Futures properly. So, what is the correct solution?
Try using the invokeAll-Method, you simply put your Callables in a List and then call invokeAll() on your ExecutorService giving it a timeout as second and third argument.
executorService.invokeAll(callableList, 20, TimeUnit.SECONDS);
I have a web application that contains a java bean for executing a potentially long-running job. I'd like to find a way that I can identify when a thread has been executing for a very long time and then potentially kill it if necessary.
My application runs in Glassfish 3 so I am on Java 1.6. I am just looking for a solution to a potential problem in the future.
EDIT:
To be clear I am looking for something like a tool or utility to monitor a running web application.
Use an Executor Service.
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Runnable(){ ....});//pass your runnable
And then you can wait for a specified time:
try {
int timeOut = 5;
//Waits if necessary for at most the given time for the computation to
// complete, and then retrieves its result, if available.
future.get(timeout, TimeUnit.SECONDS)
} catch (TimeoutException e) {
System.out.println("TimedOut!");
}
executor.shutdownNow();
I am using the JavaMail API , and there is a method in the Folder class called "search" that sometimes take too long to execute. What i want is to execute this method over a maximum period of time( say for example 15 seconds in maximum) , that way i am sure that this method will not run up more than 15 seconds.
Pseudo Code
messages = maximumMethod(Folder.search(),15);
Do I have to create a thread just to execute this method and in the main thread use the wait method ?
The best way to do this is create a single threaded executor which you can submit callables with. The return value is a Future<?> which you can get the results from. You can also say wait this long to get the results. Here is sample code:
ExecutorService service = Executors.newSingleThreadExecutor();
Future<Message[]> future = service.submit(new Callable<Message[]>() {
#Override
public Message[] call() throws Exception {
return Folder.search(/*...*/);
}
});
try {
Message[] messages = future.get(15, TimeUnit.SECONDS);
}
catch(TimeoutException e) {
// timeout
}
You could
mark current time
launch a thread that will search in the folder
while you get the result (still in thread) don't do anything if current time exceeds time obtained in 1 plus 15 seconds. You won't be able to stop the connection if it is pending but you could just disgard a late result.
Also, if you have access to the socket used to search the folder, you could set its timeout but I fear it's gonna be fully encapsulated by javamail.
Regards,
Stéphane
This SO question shows how to send a timeout exception to the client code: How do I call some blocking method with a timeout in Java?
You might be able to interrupt the actual search using Thread.interrupt(), but that depends on the method's implementation. You may end up completing the action only to discard the results.