Wednesday 16 May 2012

Pause and Resume Thread


If you want a single thread that can do start, pause, resume and stop followings  abstract class you need to extend is tested solution for you. Extend  this class, define what task you want to run in thread and it will give you methods to handle different thread life cycle stages. Please let me know if you find anything wrong :)

IMP NOTE: Remember once you call the shutdown/shutdownNow method on executor, any further attempt to submit task will throw RejectedExecutionException.

1. Pausing Normal Thread.run:


package co.rnd.thread.life;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import com.google.common.util.concurrent.Monitor;

public abstract class PausableTask implements  Runnable{

private ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<?> publisher;
protected volatile int counter;
private void someJob() {
System.out.println("Job Done :- " + counter);

}

abstract void task();

@Override
public void run() {
while(!Thread.currentThread().interrupted()){
task();
}
}

public void start(){
publisher = executor.submit(this);
}

public void pause() {
counter = 100;
publisher.cancel(true);
}

public void resume() {
counter = 200;
start();
}

public void stop() {
counter = 300;
executor.shutdownNow();
}
}

2. Pausing Scheduled Thread:
package co.rnd.thread.life;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public abstract class PausableScheduledTask
{
   private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
   private volatile boolean isPaused = false;

   abstract void task();

   public void start()
   {

         if(executor == null || executor.isShutdown())
   {
   executor = Executors.newSingleThreadScheduledExecutor();
     final Runnable beeper = new Runnable()
      {
         @Override
         public void run()
         {
            if (!isPaused)
               task();
         }
      };
      executor.scheduleAtFixedRate(beeper, getInitialDelay(), getPeriodDelay(), TimeUnit.SECONDS);
   } else
   {
   resume();
   }

     
   }

   public void pause()
   {
      isPaused = true;
   }

   public void resume()
   {
      isPaused = false;
   }

   public void stop()
   {
      executor.shutdownNow();
      executor = null;
   }

   public long getInitialDelay()
   {
      return 0;
   }

   public long getPeriodDelay()
   {
      return 0;
   }

   public TimeUnit getTimeUnit()
   {
      return TimeUnit.SECONDS;
   }
}