Alternative to Thread.suspend () and .resume ()

I have a large segment of code that is not a loop, just a list of commands that happen once, but takes some time. I need to either pause it or stop it at any time based on a changing logical value. I could use another thread to pause, resume, and stop this code, but these methods are deprecated, so I would like to avoid using them. I could check the boolean between each line of code, but I hope for a more elegant solution. Is there a good way to do this?

+5
source share
5 answers

The correct way to handle thread interruption (in this case, to pause or stop it) is naturally with Thread#interrupt() . It is designed so that you can identify safe points at which the flow can be interrupted, which for you, of course, is the point between each task. Thus, in order to avoid having to manually check your variable between each task and so that you can easily return to where you left off, you can save your tasks as a Runnable s list and remember your position in the list when you Stop:

 public class Foo { public static void runTask(Runnable task) throws InterruptedException { task.run(); if (Thread.interrupted()) throw new InterruptedException(); } Runnable[] frobnicateTasks = new Runnable[] { () -> { System.out.println("task1"); }, () -> { Thread.currentThread().interrupt(); }, //Interrupt self only as example () -> { System.out.println("task2"); } }; public int frobnicate() { return resumeFrobnicate(0); } public int resumeFrobnicate(int taskPos) { try { while (taskPos < frobnicateTasks.length) runTask(frobnicateTasks[taskPos++]); } catch (InterruptedException ex) { } if (taskPos == frobnicateTasks.length) { return -1; //done } return taskPos; } public static void main(String[] args) { Foo foo = new Foo(); int progress = foo.frobnicate(); while (progress != -1) { System.out.println("Paused"); progress = foo.resumeFrobnicate(progress); } System.out.println("Done"); } } --> task1 Paused task2 Done 
+1
source

I could check the boolean between each line of code, but I hope for a more elegant solution. Is there a good way to do this?

Unfortunately not.

To replace pause / resume, you really need one thread to “pause” another thread without involving the code of the second thread.

This cannot be done safely in Java, as it was currently implemented and implemented.

Deprecated Thread methods are the only way to kill one thread, stop / pause, resume another thread ... if the other thread does not actively collaborate. They were obsolete because (in a nutshell) such control cannot be safely implemented within the existing core generation of JVM 1 .

The best you can do is wrap the pause / resume logic in the method that the second thread calls at the appropriate points. (This should probably use wait / notify ... or the equivalent ... to solve the renewal problem. But wait / notify per se does not take into account your explicit requirement to suspend / resume a non-interacting stream.)


1 - For this you need something like the Isolates API. There have been attempts to implement it in research projects, but AFAIK Isolates has never been implemented in a production JVM.

+4
source

You can use wait / notify as an alternative to pause / resume. Instead of stopping, you can set a flag, notify and throw an exception from the notified stream

+1
source

There is excellent documentation on why Thread.stop() , Thread.pause() and Thread.resume() are deprecated:

Bright outdated version of Java Thread

There is also an alternative for Thread.pause() / Thread.resume() with an explanation of wait and notify .

+1
source

I have an idea how to do this with AspectJ. The solution that I set out below will allow you to pause / resume another thread. This pause will take effect when you call the next method from your target method after calling the pause procedure. This will not require logical checks after each line of code of your target method. I use wait / notify for this.

I am using Spring in the example below.

First roll up your target method in Runnable.

  package com.app.inter.thread.communication.runnables; public class TestRunnable implements Runnable{ public void run() { long i=0; //For explanatory purposes, I have used an infinite loop below //and printed an increasing number while(!Thread.interrupted()){ //someService.action1(); //someService.action2(); //.... if(i++%10000000==0) System.out.println("Working "+i); } } } 

Then you will create an aspect that will be conditionally called when the method is called inside your target method.

 @Aspect @Component public class HandlerAspect { public static volatile boolean stop=false; public static volatile String monitor=""; @Pointcut("withincode(public void com.app.inter.thread.communication.runnables.TestRunnable.run()) " + "&& call(* *.*(*)) " + "&& if()") public static boolean stopAspect(){ return stop; } @Before("stopAspect()") public void beforeAdvice(JoinPoint jp) { try { System.out.println("Waiting"); synchronized(monitor){ monitor.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } stop=false; } } 

Now that you want to pause your stream, just set the stop value to true, and vice versa.

 @Service public class Driver { @Autowired private HandlerAspect aspect; @PostConstruct public void init(){ Scanner scanner = new Scanner(System.in); int i=-1; TestRunnable runnable = new TestRunnable(); Thread thread= new Thread(runnable); thread.start(); aspect.monitor="MONITOR"; while((i=scanner.nextInt())!=0){ switch(i){ case 1: aspect.stop=true; break; case 2: aspect.stop=false; synchronized(aspect.monitor){ aspect.monitor.notify(); } break; } } // in case the main thread is stopped // while the other thread is in wait state synchronized(aspect.monitor){ aspect.monitor.notify(); } thread.interrupt(); } } 

The output is as follows:

 ... Working 400000001 1Working 410000001 Working 420000001 Working 430000001 Working 440000001 Working 450000001 Working 460000001 Working 470000001 Waiting 2 Working 480000001 Working 490000001 0 

The working code is at https://github.com/zafar142007/InterThreadCommunication

+1
source

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


All Articles