0

I need to set a timeout for a block of code which will call an method in jar file. I am using the following code

final Runnable stuffToDo = new Runnable() {
          @Override 
          public void run() { 
            /* Do stuff here. */ 
              jarclass.run();
          }
    };

    final ExecutorService executor = Executors.newFixedThreadPool(1);
    final Future future = executor.submit(stuffToDo);
    //executor.shutdown(); // This does not cancel the already-scheduled task.
    try { 
      future.get(1, TimeUnit.SECONDS); 
    }
    catch (InterruptedException ie) { 
      /* Handle the interruption. Or ignore it. */ 
    }
    catch (ExecutionException ee) { 
      /* Handle the error. Or ignore it. */ 
    }
    catch (TimeoutException te) { 
      /* Handle the timeout. Or ignore it. */ 
    }
    if (!executor.isTerminated()){
        executor.shutdownNow();
    }

However the jarclass.run() somehow start another thread which keep running and show all the printout with pool-2-thread-1.

How can I completely shutdown the jarclass.run()??

Update: I changed new Thread() to new Runnable. It still doesn't work. What I am confusing is I don't know where jarclass start another thread and cannot handle it. When the code goes to executor.shutdownNow(), it does jump out and run the following code. But the jarclass.run() are still running. I am not very good at English. Hope I made this clear.

Update:

Problem solved by this code:

Future<String> future = new FutureTask<String>(new Callable<String>() {
        public String call() throws Exception {
            jarclass.run();
            return null;
        }
    });

    try {
        future.get(1, TimeUnit.SECONDS);
    } catch (Exception e) {
        e.printStackTrace();
    }

Don't know why the former code fail......If anyone knows, we can still discuss.

Thanks for all the kindly replies. Really appreciate it.

  • You might want to use a Thread directly and call its *interrupt* method. But I am not so sure if that will work. – GhostCat Mar 15 '17 at 08:36
  • [`shutdown`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--) will only prevent adding new tasks but allow already running ones to finish: "Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted." You could try to call [`cancel`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html#cancel-boolean-) (with interruption) on the future on TimeoutException. – Fildor Mar 15 '17 at 08:37
  • BTW: You don't need to make stuffToDo a `new Thread`, `new Runnable` will do. This may seem odd because it is an interface, but actually you are creating an anonymous class implementing the interface. – Fildor Mar 15 '17 at 08:41
  • After Update: So you are saying the method you call in the jar creates a Thread. That means that thread should be "accessible" as a child of your PoolThread. You should be able to react to interruption inside your run method and try to propagate interruption to all child threads. – Fildor Mar 15 '17 at 09:14
  • It should be. Child thread will be interrupted when parent thread is interrupted. But it is really weird. And I have read the code in jar class I don't find any new thread().....I just can not terminate it.....Seems like all the code in jarclass.run() are put into another thread pool and it keeps printing pool-2-thread-1 info.... – user1703532 Mar 15 '17 at 09:25
  • You have no timeout code. You just set one and catch the exception. But as is, you ignore it. You should cancel the future in the catch clause of TimeoutException. And your check for isTerminated will always hit, because you do not shutdown the pool before. Docs: "Returns true if all tasks have completed **following shut down**. Note that isTerminated is never true unless either shutdown or shutdownNow was called first." – Fildor Mar 15 '17 at 09:26
  • I guess the jar's run method does not include a check for interrupt status (which is bad, IMHO). What is it doing? Can you close an underlying stream to force it to terminate the thread? Are you using the API correctly? – Fildor Mar 15 '17 at 09:37
  • I'm sorry what do you mean the underlying stream specifically? The run() method will start an analysis program. If I do not try to add time out for it, it will run perfectly. But it will run out memory if it run on large program. So I want it to stop if it can not get any result. Btw I really appreciate all your reply. This problem really drive me crazy..... – user1703532 Mar 15 '17 at 09:46

2 Answers2

0

You should not instantiate a Thread when using ExecutorService. Use Runnable instead:

final Runnable stuffToDo = new Runnable() { /* as it is now */ };

When you create a thread directly, it's not managed by the executor service you create later and that's why all the logs.

nobeh
  • 9,784
  • 10
  • 49
  • 66
  • I don't believe so. I agree he should be using `new Runnable` but passing it to the ExecutorService will just mean the Service will use the Thread's `run`method. Since he does not *start* the Thread, it's still going to work. – Fildor Mar 15 '17 at 09:09
0

It's not safe kill thread directly, see Thread.stop() deprecated

Recomended way it to use a flag that can notify to thread that is time to stop.

If you can access to jar and modify code you can create a method named stop() in your jarclass using flag so when you need to kill process you can call jarclass.stop().

For example:

public class jarclass{

  private boolean keepAlive = true;

  public void run(){

     keepAlive = true;
     while(keepAlive){
       //do work
     }
  }

  public void stop(){
    keepAlive = false;
  }
}
David Geirola
  • 616
  • 3
  • 17
  • This might work but I will consider altering the jarclass as the last option due to some copyright issue. Hope I can come up with other solutions. But thanks anyway. – user1703532 Mar 15 '17 at 08:59
  • Yes is not a great solution, but if method run() of jarclass start a new threads and you haven't any reference to them, i see a few solutions – David Geirola Mar 15 '17 at 09:31
  • I am not sure whether run() has started a new thread or not. I go through the jarclass code but don't find any new Thread() statement. But all the message in run() is printed with pool-2-thread-1. And the main program flow did skip jarclass.run() but did not terminate it. – user1703532 Mar 15 '17 at 09:35