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;
}
}
Hello
ReplyDeleteIts good to see the code , but it has 1 bug
if(executor == null || executor.isShutdown())
{
executor = Executors.newSingleThreadScheduledExecutor();
} else
{
resume();
}
In above code the control never goes inside "if" statement
In scenario
start 1st time
pause
start 2nd time
two different executors are scheduled to run
so whatever you write in task() function gets executed twice after second start
try running your PausableScheduledTask by putting some print stmt inside task() function and run the above scenario from main class
Attaching the modified code
public class PausableScheduledTask {
private ScheduledExecutorService executor = null;
private volatile boolean isPaused = false;
public void task(){
System.out.println("Hello world !!!!");
}
Runnable scheduler = new Runnable() {
@Override
public void run() {
if (!isPaused)
task();
}
};
public void start() {
if (executor == null || executor.isShutdown()) {
System.out.println("Restarting");
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(scheduler, getInitialDelay(), getPeriodDelay(), TimeUnit.SECONDS);
} else {
System.out.println("RESUMED IN START");
resume();
}
System.out.println("i am here");
}
public void pause() {
System.out.println("its paused");
isPaused = true;
}
public void resume() {
System.out.println("its resumed");
isPaused = false;
}
public void stop() {
executor.shutdownNow();
executor = null;
}
public long getInitialDelay() {
return 0;
}
public long getPeriodDelay() {
return 2;
}
public TimeUnit getTimeUnit() {
return TimeUnit.SECONDS;
}
}
Main method
ReplyDeletepackage com.alu.scheduler;
public class TestScheduler {
public static void main(String[] args) {
PausableScheduledTask fileSyncScheduler = new PausableScheduledTask();
fileSyncScheduler.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
fileSyncScheduler.pause();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
fileSyncScheduler.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
fileSyncScheduler.stop();
}
}
Hi Ashish, Thanks for your efforts but multiple instance of beeper or scheduler is caused by your twice call to start(). In your test you should have called start(), pause() then resume() instead of start(). Anyway I have modified the code to handle this scenario as well. Thanks for comment
Delete