1

I have thread application which process heavy task, i would like to trigger forcibly stop thread upon external flag information. I have tried following design,

public class HeavyTaskThread implements Runnable
{
   private boolean forceStop;

   public void run()
   {
     ..
     ..
     ..
     ..
   }
}

Another fact is i do not have control of logic flow implemented into method run(); which simply call some third-party program. I was trying with light inner thread class and calling method interrupt() on parent thread, but this does not work.

Please suggest any pattern....

5 Answers 5

3

The recommended way to handle the activity of third-party code that you have no control over is to launch it as a different process instead. Then simply kill the process when you need to forcibly stop the code. It's much more clean and safe than killing a thread, since it does not affect the parent process and the OS will take care of the cleanup duty.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 This is an excellent idea if the third-party code is already designed to run as a command line app. If it is designed to run as a direct API call, e.g. thirdPartApp = new ThirdPartyApp(); thirdPartyApp.doSomething(arguments); then you'll need to do a little extra work to persist the arguments and write a little main() to read back the arguments and make the call.
1

If the third party program doesn't respond to an interrupt or setting a condition, an icky option is to try to kill it by nulling a key variable, closing a socket or file, etc. And hoping that it terminates gracefully. Like I said, icky but sometimes you gotta do what you gotta do...

Comments

0

If whatever third-party program you call in run() never returns, you're out of luck. If it returns periodically, you can make it loop, checking against a volatile forceStop boolean and exiting the loop when it's true:

private volatile boolean forceStop;

public void run()
{
    while(!forceStop) {
        ..
        ..
    }
}

3 Comments

What if he external code is just a method which should be called once.Then the above code wont help.
thanks for quick reply, but this solution does not work. I have to some how stop the thread. As i said, i had that lightweight thread to pull "forceStop" and had passed main thread instance and called interrupt().
@user1109059 Like I said, unless you can watch for a variable or invoke an interrupt(), you're out of luck. You can't stop that thread. There used to be a stop() method, but it was unsafe.
0

While I'd vote for Tudor's answer, in the extreme and if you're desperate:

Option A - Reconstruct problem code.

  • Use your favorite java decompiler & re-create problem class.

  • Add check for Thread.currentThread().isInterrupted() into run.

  • Compile, place your modified class before original library in the classpath.

  • If the original jar was signed you may have to eliminate related signature artifacts.

Option B - Aspect J

  • Examine source for the run method, use your favorite java decompiler if necessary.

  • Identify a some reasonable point in the inner loop for stepping in and stopping.

  • Examine exception handling in code. Any loop-holes?

  • Inject code: throw exceptions, catch exceptions, etc. as needed to back out and return from run.

Comments

0

Here is final analysis...for killing thread.

  1. Using Thread to control the execution of Program B. But then stopping a process means via a thread is not allowed as the related methods are deprecated (stop/suspend etc.,)

  2. Using ThreadGroup ( to have only one thread as its member) and calling 'destroy' on the group. But it again falls on the same track as every thread should be stopped before the destroy operation is attempeted.

  3. Process/ProcessBuilder via Runtime seems to be the better way to obtain a process reference and call destroy(), waitFor() etc. as user @Tudor mentioned.

Here is exact outlined code i have tried and it fails to kill, commented line while(isValid()) represents my another java program invoke.



    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CompletionService;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;

    class TaskWorker implements Callable {
        private final int number;

        public TaskWorker(int number) {
            this.number = number;
        }

        public Boolean call() throws InterruptedException {
            while (!Thread.currentThread().isInterrupted()) {
                myBusyFunction();
            }
            return true;
        }

        private boolean isValid() {
            return true;
        }

        private void myBusyFunction() {
            //while (isValid()) {
            System.out.println(number + ">....Working.....");
            //}
        }
    }

    public class Test {
        public static void main(final String[] args) {
            CompletionService cs = new ExecutorCompletionService(Executors.newFixedThreadPool(1));
            Collection tasks = new ArrayList(10);
            tasks.add(new TaskWorker(1));
            List> futures = new ArrayList>(tasks.size());
            try {
                for (Callable task : tasks) {
                    futures.add(cs.submit(task));
                }
                //----
                for (int t = 0; t  result = cs.poll(10, TimeUnit.SECONDS);
                    if (result == null) {
                        System.out.println(new Date() + ":Worker Timedout:");
                        //So lets cancel the first futures we find that havent completed
                        for (Future future : futures) {
                            System.out.println("Checking future");
                            if (future.isDone()) {
                                continue;
                            } else {
                                future.cancel(true);
                                System.out.println("Cancelled");
                                break;
                            }
                        }
                        continue;
                    } else {
                        try {
                            if (result.isDone() && !result.isCancelled() && result.get()) {
                                System.out.println(new Date() + ":Worker Completed:");
                            } else if (result.isDone() && !result.isCancelled() && !result.get()) {
                                System.out.println(new Date() + ":Worker Failed");
                            }
                        } catch (ExecutionException ee) {
                            ee.printStackTrace(System.out);
                        }
                    }
                }
            } catch (InterruptedException ie) {
            } finally {
                //Cancel by interrupting any existing tasks currently running in Executor Service
                for (Future f : futures) {
                    f.cancel(true);
                }
            }
            System.out.println(new Date() + ":Done");
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.