How to interrupt Thread when it is inside some kind of loop, performing a long task?

Possible duplicate: How do you kill a thread in Java?


I need to stop a large task by sending an interrupt signal to Thread. I use most of the APIs from java.util.concurrent. *. My task is to send to Thread and execute. This task comes from the client, so I do not control this code.

The task is similar to:

public class Task1 extends Thread { public void run() { while(true){ if(Thread.interrupted()){ return; } for(int i=0; i<Integer.MAX_VALUE; i++){ System.out.println("I am task 1 " + i); } } } }; 

I want to basically stop the loop through the for loop when it receives the interrupt signal (note that I cannot put the Thread.interrputed () logic inside the loop because it comes from the client.) I have another class that use the Executor to complete this task.

 public class ConcurrentTest { public static void main(String[] args) { // TODO Auto-generated method stub ConcurrentTest test = new ConcurrentTest(); ExecutorService executorService = Executors.newFixedThreadPool(2); Task1 task1 = new Task1(); Future<?> runningTask1 = executorService.submit(task1); Task2 task2 = new Task2(); Future<?> runningTask2 = executorService.submit(task2); //Stop First task after 5 second try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } runningTask1.cancel(Boolean.TRUE); System.out.println("runningTask1.isDone is " + runningTask1.isDone()); System.out.println("runningTask1.isCancelled is " + runningTask1.isCancelled()); //Stop Second task after 10 second try{ TimeUnit.SECONDS.sleep(3); }catch(InterruptedException e){ e.printStackTrace(); } runningTask2.cancel(Boolean.TRUE); System.out.println("runningTask2.isDone is " + runningTask2.isDone()); System.out.println("runningTask2.isCancelled is " + runningTask2.isCancelled()); } 

}

Task 2:

 public class Task2 extends Thread{ public void run() { while(true){ if(Thread.interrupted()){ return; } System.out.println("I am task 2"); } } }; 

Task2 is interrpted, however Task1 is never interrupted and continues execution inside the loop. I can’t put the logic inside the client code (something similar to for-loop). I need help from the SO community to solve this problem. Thanks.

+1
source share
9 answers

The only harmless solution is to run client code in isolation. Isolation is essentially a private virtual machine with which a Java application can create, manage, and share data. In particular, a parent application can safely kill isolation and all its threads.

Reference: JSR-000121 Application Isolation API Specification - Final Release

The problem is finding a JVM that supports Isolates.

+3
source

Reread your questions and realize that you do not have control over the task code.

The reason why task1 does not interrupt is because the interrupt () method does not actually interrupt anything, it will only interrupt the thread if this thread expects some lock or sleep mode, otherwise it actually does nothing but setting status.

The only way to kill task1 for you is to use the Thread.stop () method. Be careful, although this can be very dangerous and make your system unstable. More details here .

+2
source

You can use the stop flag and shell class to kill both your own tasks and those that the client gives you.

 public class MyTask implements Runnable { private TaskController taskControl; @Override public void run() { if(taskControl.abort()) { return; } // Task logic ... } } // Construct on main thread, call "run()" on a dedicated background thread. public class TaskController implements Runnable { private AtomicBoolean terminate = new AtomicBoolean(false); private ThreadPoolExecutor yourTaskThreadPool; private ThreadPoolExecutor otherTaskThreadPool; @Override public void run() { // Your task construction, dispatch logic. Use your own thread pool // Run the tasks you don't control in THEIR own pool if(terminate.get()) { otherTaskThreadPool.shutdown(); } otherTaskThreadPool.execute( clientsTask ); // eg "task1" } public void AbortAllTasks() { terminate.set(true); } public boolean abort() { return terminate.get(); } } 

Your tasks can take a controller (pointer "this") as a construction parameter and check the completion flag in run() . This allows you to kill all of them asynchronously by simply calling TaskController.AbortAllTasks() . For tasks that you do not control, you can put your own interrupt logic in TaskController.run() .

+2
source

Interruption is indeed a mechanism for canceling cooperation , not a preventive one. Collaboration is required to make a graceful cancellation. If a task is uninterrupted (i.e., does not interrupt its operation by checking the status of an interrupt or responding to an InterruptedException), you cannot do this to cancel the task. Giving an interrupt is trivial; this is really how the task answers it.

One possible solution would be to embed your code in a task using features such as dynamic hardware. However, even this is not a sure bet, and you would need to insert the code inside the while loop if the task uses the while loop.

+1
source

I would provide a mechanism that allows client code to interact with a stop signal. If the client code processes the signal, your application and client agree that it can be stopped in a timely manner. Otherwise, you interrupt the thread when the code returns to your interrupt () check. I want to say that you should ask the client code to work, and not interrupt it blindly.

+1
source

Check the interrupt twice inside the while loop and in the for loop.

  while(true){ if(Thread.interrupted()){ return; } for(int i=0; i<Integer.MAX_VALUE; i++){ if(Thread.interrupted()){ return; } System.out.println("I am task 1 " + i); } } 
0
source

If someone else provides the code in the workflow (like a bank?), Do they even call your code part of their work? You can put a check on the interrupted function that you write, which they call, and throw an thrown exception, which we hope will end the thread.

 // Called from the worker thread code that someone else writes, // hopefully often so that we notice when we're interrupted. public void doSomething() { if (Thread.interrupted()) { throw new MyRuntimeException(); } // do what this method is meant to do ... } 

Be careful to warn developers about writing this code: see this article for some issues that may arise .

So, in short, if you are not writing this code, it is best to try to figure out who should check Thread.interrupted () so that they can exit normally.

0
source

A simple approach to stopping threads is to define a stop sign for each thread and then periodically check this flag.

For instance:

 class MyTask implements Runnable { private AtomicBoolean stopflag = new AtomicBoolean(); public void stop() { stopflag.set(true); } public void run() { while(true) { if(!stopflag.get()) /// do some work else return; // get out } } } 
0
source

You cannot do this without modifying the for statement itself. since the Sun has destroyed the methods of immediately suspending Thread. and they had their own reasons. ( see here ) the only way to do this is to use a boolean inside the loop or, if Thread sleeps \ wait inside the for loop, you can catch the InterruptedException that Thread.interuppt () throws

0
source

Source: https://habr.com/ru/post/1489991/


All Articles