Kill a Java Thread without looping - java

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.

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

Java - proper cancel execution of thread after TimeoutException

I have a java-program which runs on a schedule and fetches some data from external sources via RFC calls. The RFC calls are threaded and shall be canceled after 60 seconds. This is how I do it:
Future<String> future = executor.submit(new MyCallable());
try {
future.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
}
This worked for a long time until I came accross a situation, where the external RFC call became stuck and future.cancel(true) was unable to interrupt the thread-execution. So my java-program never finished and continued running until I manually canceled the corresponding process within the external system.
My question now is, how can one guarantee the code to finish in any situation? I saw that stopping the thread is depreciated.
Would it be a good idea to do sth like this?
try {
future.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
if(!future.isDone()){
System.exit(1);
}
}
Thanks for any ideas on this.
Cheers, Jooo
I believe that there's no way in Java to just kill off a thread if during execution not implemented InterruptedException . If the thread is executing, it just sets a flag and it's up to the thread to notice it. if the thread is waiting or sleeping, it will throw an InterruptedException.
No need to check after every line, of course, but methods which can take a long time to execute are responsible for properly handling interrupts
kill the process in which the thread is running. (E.g., call System.exit(int).)

How can I stop/pause particular thread from ExecutorService?

I have spring scheduler method. And ExecutorService
#Scheduled(fixedRate = 5000)
public void startSchedule() throws IOException{
threadPool.submit(() -> {
if(.......)return;
try {
generate(reportTasck);
} catch (NurException | IOException e) {
e.printStackTrace();
}
});
}
Each 5 sec start my method and if a necessary condition - start new thread with my logic. How can I stop/pause particular thread?
I have button on veb page, and if I press it I need to stop my thread.
There is already quite some discussion on SO regarding the stopping of threads. For a variety of reasons you should not stop or kill a thread as e.g. noted here:
How do you kill a thread in Java?
In order to allow the thread to properly cleanup its resources it should be the thread's responsibility to terminate itself by e.g. periodically checking some condition using e.g. a shared variable or via the thread's interrupt flag. See this answer for more details:
How to stop a thread created by implementing runnable interface?

Kill or stop a endless/not-returning-value thread in Java

I have a function in Java. It normally returns a value after it completes its task. However, in some conditions it returns nothing. I create a runnable and run this function as a thread. However, because of its not returning a value, it does not finish although it does its task. The process stays alive because it waits a returning value. Is there a way to kill this thread after it is triggered or after a timeout? Stop() or Destroy() did not work. During debug, the thread is seen as alive and I want it to bi deleted/removed
Runnable runnable = new Runnable() {
#Override
public void run() {
int stat = RunMyFunction();
}
};
Thread thread = new Thread(runnable);
thread.start();
Java does not support killing a thread via any method on java.lang.Thread.
stop() and destroy() do look promising at first glance, but they have both been deprecated.
The documentation for destroy states:
This method was originally designed to destroy this thread without any cleanup. However, the method was never implemented. If if were to be implemented, it would be deadlock-prone
and stop:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
Thus when the documentation says 'deprecated', what it really means is that they are broken and must never be used!?! The Java API designers put a lot of work into backwards compatibility of their APIs, where other languages would have removed these methods Sun decided to keep them as their internal guides (rightly or wrongly) do not permit the removal of a public api method.
So, the question remains. How is one to get a thread to exit from another thread? Sadly one must go out of ones way to poll an exit variable. This can be a custom variable, or it can be a standard flag within java.lang.Thread that is accessible via 'interrupted()'. The advantage of using interrupted() is that other Java APIs such as IO support this flag during otherwise blocking API calls and will exit throwing an InterruptedException. The detection of calling interrupt() is not immediate, as it sets a flag and relies on the Thread to poll the variable at some point in the future.
Oracle offers a tutorial on how to code using interrupt here.
The real problem you have is that RunMyFunction sometimes never terminates. As others have already stated, killing a thread is not intended in Java, so there is no good way to do it. Instead, you should reason about why you call a possibly non-terminating method. This looks like a code smell. Do the following:
If you are the author of RunMyFunction, make sure that it always terminates or it can be interrupted. You can do this by checking Thread.currentThread().isInterrupted() and throwing an InterruptedException when it is. E.g:
void run(){
while(...){ // this loop sometimes runs forever
if(Thread.currentThread().isInterrupted())
throw new InterruptedException(); // Now, we can "kill" this thread here
}
}
Using ExecuterService you can specify a timeout.
ExecutorService executor = Executors.newFixedThreadPool(1);
List<Callable<String>> tasks = new ArrayList<Callable<String>>();
tasks.add(new Callable<String>() {
#Override
public String call() throws Exception {
int stat = RunMyFunction();
return "Execution Finished";
}
});
new Thread(new Runnable() {
#Override
public void run() {
try {
executor.invokeAll(tasks, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
invokeAll(...) is a blocking call so i've added inside a new thread.
Solution 1: Timed run: If you want a method to return or throw an exception after a specified amount of time, use the following method to execute the method on a background thread while waiting for it to complete:
public static void timedRun(Runnable r, long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
Future<?> task = executor.submit(r);
try {
task.get(timeout, unit);
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
} finally {
task.cancel(true);
}
}
private static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException) return (RuntimeException)t;
else if (t instanceof Error) throw (Error)t;
else throw new IllegalStateException("Not unchecked", t);
}
(Source: Goetz, Brian, Bloch, Joshua, Bowbeer, Joseph, Lea, Doug, Holmes, David and Peierls, Tim. Java Concurrency in Practice. : Addison-Wesley Longman, Amsterdam, 2006. Listing 5.13 and 7.10)
For executor, you can either create a new one using Executor.newSingleThreadExecutor(), or reuse an existing one.
But be warned: Although this method is guaranteed to return or throw an exception after the specified timeout, it cannot guarantee that the runnable will really stop! It interrupts the executing thread, but if the runnable does not react to thread interruption (e.g. by internally checking Thread.interrupted()), it may continue to run in the background - possibly forever - occupying a thread! But at least it does not block.
Solution 2: Timed run with custom threads: If there is any possibility beside thread interruption to cancel your method call, you can still use the approach above, but then you have to use an Executor with custom ThreadFactory that creates a special Thread instance with overridden interrupt method:
Executor executor = Executor.newSingleThreadExecutor(r -> new WsdlThread(r));
public class WsdlThread extends Thread {
public WsdlThread(Runnable r) { super(r); }
public void interrupt() {
try {
// TODO: do something that will interrupt the wsdl call
// e.g. close connection to server, etc.
// example: ((WsdlRunnable)r).getWsdlConnection().close();
} finally {
super.interrupt();
}
}
}
If this isn't possible too, and Thread.stop() doesn't work either, this last solution might work:
Solution 3: Start non-cancellable call in another JVM:
Use Runtime.exec to start another JVM and execute the method call there (See Executing a Java application in a separate process for more info on how to do this). Runtime.exec will return a Process object, which represents the running process.
You can kill it by calling destroy() or destroyForcibly().

Java - stopping all tasks in ExecutorService

I have a few executor services which schedule local tasks such as reading a file, connecting to db etc. These processes do huge amount of logging, which is extensive based on the fact there are many threads running concurrently, writing their own thing into the log.
Now, at some point in time an exception can be raised, which reaches the main method where all exceptions are caught. I am then shutting down all the services and cancelling each task, hoping to prevent all further messages to the log. Unfortunately, the messages are still showing up after I shut everything down... Any ideas?
UPDATE:
Here is some code
public class Scheduler{
private final ExecutorService service;
private final ConcurrentMap<Object, Future<V>> cache;
...
public void shutDown() {
service.shutdownNow();
for (Future task : cache.values())
task.cancel(true);
}
The task will carry on running until it reaches a point where it detects the Thread has been interrupted. This can happen when calling some System or Thread functions and you may get an exception thrown. In your case you probably need to check yourself by calling
Thread.currentThread().isInterrupted()
It is a good idea to do this if your code runs loops and you are expecting to be stopped in this way.
When you shutdownNow your executor or call cancel(true) (by the way shutdownNow already cancels the already submitted tasks so your loop is unnecessary) your tasks get interrupted.
Depending on how they react to the interruption, they might then:
stop what they are doing immediately
stop what they are doing after a while, because the interruption signal is not being checked regularly enough
continue doing what they are doing because the interruption signal has been ignored
For example, if your tasks run a while(true) loop, you can replace it with something like:
while(!Thread.currentThread().isInterrupted()) {
//your code here
}
cleanup();
//and exit
Another example:
for (int i = 0; i < aBigNumber; i++) {
if (Thread.currentThread().isInterrupted()) { break; }
//rest of the code for the loop
}
cleanup();
//and exit
Another example, if you call a method that throws InterruptedException:
try {
Thread.sleep(forever); //or some blocking IO or file reading...
} catch (InterruptedException e) {
cleanup();
Thread.currentThread.interrupt();
//and exit
}
Executors support 2 approaches of shutdown
shutdown() : Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
shutdownNow() : Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks.
Ref : http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
- Try using the shutdowNow() method, it will shutdown all the task started by this Executor throwing InterruptedException, but IO and Synchronized operation can't be interrupted.
Eg:
ExecutorService executor = Executors.newFixedThreadPool();
executor.execute();
...
...
executor.shutdownNow();
- cancel(true) method can be used with submit() method to shutdown a particular task.

Categories

Resources