This discussion is archived
7 Replies Latest reply: Feb 7, 2013 11:06 AM by meandmycode RSS

Thread is blocking when using a timed thread with executorservice

meandmycode Newbie
Currently Being Moderated
Hi,

I originally had the following code:
execMgr = new ExecutionManagementThread(listener, process);
     execMgr.setDaemon(true);
     execMgr.start();
The execMgrThread looks like this ( see below). Purpose of this thread is to keep a process with a native command running.

     private static class ExecutionManagementThread extends Thread {
          private boolean finished = false;
          private OperationListener opListener = null;
          private Process process = null;
          /**
           * Creates a new instance.
           * 
           * @param opListener
           * @param process
           */
          public ExecutionManagementThread(OperationListener opListener,
                    Process process) {
               super("CC Execution Management");
               this.opListener = opListener;
               this.process = process;
          }

          @Override
          public void run() {
               while (!finished) {
                    try {
                         sleep(250);
                    } catch (InterruptedException ex) {
                    }
                    synchronized (this) {
                         if (opListener != null && opListener.isCanceled()) {
                              process.destroy();
                              finished = true;
                         }
                    }
               }
          }
          
          

          public synchronized void setOperationListener(OperationListener ol) {
               opListener = ol;
          }

     }
However I need this process to be timed meaning it should run for a specific amount of time and then finish. So I decided to use ExecutorService.

So I created a executorService:
 private static ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
               
               public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r, "ExecutionManagerThread");
                    thread.setDaemon(true);
             return thread;
               }
          });
And instead of extending a Thread for execMgr I use a Runnable:
private static class ExecutionManangementRunnable implements Runnable{
          
          private boolean finished = false;
          private OperationListener opListener = null;
          private Process process = null;

          /**
           * Creates a new instance.
           * 
           * @param opListener
           * @param process
           */
          public ExecutionManangementRunnable(OperationListener opListener,
                    Process process) {
               this.opListener = opListener;
               this.process = process;
          }

          /* (non-Javadoc)
           * @see java.lang.Runnable#run()
           */
          public void run() {
               while (!finished) {
                    try {
                         Thread.sleep(250);
                         
                    } catch (InterruptedException ex) {
                    }
                    synchronized (this) {
                         if (opListener != null && opListener.isCanceled()) {
                              process.destroy();
                              finished = true;
                         }
                    }
               }
               
          }
          
          public synchronized void setOperationListener(OperationListener ol) {
               opListener = ol;
          }
          
     }
Then to create the timed thread I use the following code:
public static void timedRun(Runnable r , long timeout, TimeUnit unit) throws InterruptedException{
          Future<?> task = executorService.submit(r);
          
          try {
               task.get(timeout, unit);
          } catch (TimeoutException e) {
               System.out.println("task got timeout!");
               //task cancelled in finally
          }catch (ExecutionException e) {
               System.out.println("task got execution exception");
          }finally{
               System.out.println("cancel task...");
               task.cancel(true);
               System.out.println("task canceled...");
          }
     }
The above code work in the sense that it created the thread and keep the process alive for a specifc amount of time.
The problem I have with timedRun is that it blocks. So the runnable is executed but blocks other threads.
I am suspecting that the last code snippet is not correct. It seems to be waiting for the task to finish or timeout and blocks.
How can I make the thread execute for a specific time or finish without it blocking?

( Sorry for posting so much code but I could not keep it to a small code snippet ( for background info.)

br,

//mike
  • 1. Re: Thread is blocking when using a timed thread with executorservice
    Kayaman Guru
    Currently Being Moderated
    meandmycode wrote:
    I am suspecting that the last code snippet is not correct. It seems to be waiting for the task to finish or timeout and blocks.
    That's what Future.get() does. Blocks until a result is available, or a timeout (if time is specified) occurs.
    If you don't want that to block, you'll need a separate thread for your timedRun.
  • 2. Re: Thread is blocking when using a timed thread with executorservice
    meandmycode Newbie
    Currently Being Moderated
    ok. Do you mean that I need to change this:

    newSingleThreadExecutor(ThreadFactory threadFactory)

    to:

    newFixedThreadPool(int nThreads, ThreadFactory threadFactory)

    or is there another way of dong this?

    br

    //mikael
  • 3. Re: Thread is blocking when using a timed thread with executorservice
    Kayaman Guru
    Currently Being Moderated
    meandmycode wrote:
    ok. Do you mean that I need to change this:

    newSingleThreadExecutor(ThreadFactory threadFactory)

    to:

    newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
    No, that has nothing to do with it.
    Your Future.get() call blocks the current thread as it should. If that's something you don't want, then you'll need to run it in a separate thread. How you choose to do that is up to you, but I wouldn't bother with a threadpool or an executor for something as simple as that.
  • 4. Re: Thread is blocking when using a timed thread with executorservice
    meandmycode Newbie
    Currently Being Moderated
    I tried to run it in a separate thread:
    executionMgr = new ExecutionManangementRunnable(listener, process);
                   Callable callable = Executors.callable(executionMgr, null);
                   FutureTask future = new FutureTask(callable);
                   Thread thread = new Thread(future);
                   thread.setDaemon(true);
                   thread.start();
                   
                   try {
                        future.get(1, TimeUnit.MINUTES);
                   } catch (InterruptedException e) {
                        // TODO handle catch block
                        e.printStackTrace();
                   } catch (ExecutionException e) {
                        // TODO handle catch block
                        e.printStackTrace();
                   } catch (TimeoutException e) {
                        // TODO handle catch block
                        e.printStackTrace();
                   }
    I still get the same problem with main thread being blocked. Does anyone know why?'

    //mikael
  • 5. Re: Thread is blocking when using a timed thread with executorservice
    jtahlborn Expert
    Currently Being Moderated
    meandmycode wrote:
    I still get the same problem with main thread being blocked. Does anyone know why?'
    because you are still doing the same thing (calling Future.get() on the main thread).
  • 6. Re: Thread is blocking when using a timed thread with executorservice
    Kayaman Guru
    Currently Being Moderated
    meandmycode wrote:
    I still get the same problem with main thread being blocked. Does anyone know why?'
    In your main thread, start a new thread. Now your main thread won't be blocked. In your new thread, do all the things you're doing now. Voilà!

    Or don't you know how to handle threads without the higher level constructs (executors etc.)? If so, I'd recommend brushing up on them.
  • 7. Re: Thread is blocking when using a timed thread with executorservice
    meandmycode Newbie
    Currently Being Moderated
    Thanks!

    No problem I know how I can create a regular thread so the code became the following:

         Thread thread = new Thread(){
                   public void run(){
                        try {
                                  timedRun(executionMgr,30,TimeUnit.MINUTES);
                             } catch (InterruptedException e) {
                                  // TODO handle catch block
                                  e.printStackTrace();
                             }
                   }
                   };
                   
                   thread.start();

    //mikael

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points