Here is a design to achieve a simple model in Java which uses a Thread
and has these features:
- Starting the thread with an initial value
- Pausing the thread
- Resuming the thread with new value
- Stopping the thread
Restrictions: Do not use already implemented java libraries (from the concurrent package).
A similar question was asked on SO where I have answered with this code, but I want to get some review comments for the same.
I defined an interface for the model:
/**
*
* @author krishna.k
*
* This defines the methods for the model.
*
*/
public interface IResumable {
/**
* starts the model
*/
public void requestStart();
/**
* requests the model to pause
*/
public void requestPause();
/**
* requests the model to resume with new parameter
* @param newParam
*/
public void resumeWithNewParam(int newParam);
/**
* terminate the model
*/
public void requestStop();
}
The concrete Model:
public class ResumableModel implements IResumable {
private Thread worker;
private WorkerRunnable work;
public ResumableModel(int initialValue) {
work = new WorkerRunnable(initialValue);
worker = new Thread(work);
}
@Override
public void requestStart() {
worker.start();
}
@Override
public void requestPause() {
work.setPauseRequested(true);
}
@Override
public void resumeWithNewParam(int newParam) {
work.setNewParam(newParam);
}
@Override
public void requestStop() {
worker.interrupt();
}
private static class WorkerRunnable implements Runnable {
private int param; // we can have the variable of the type depending
// upon
// the requirement.
private final Object lock = new Object();
private volatile boolean isPauseRequested = false;
public void run() {
synchronized (lock) {
try {
while (!Thread.currentThread().isInterrupted()) {
while (isPauseRequested) {
lock.wait();
}
System.out.println("value of param is" + param);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public WorkerRunnable(int param) {
this.param = param;
}
private void setPauseRequested(boolean isPauseRequested) {
this.isPauseRequested = isPauseRequested;
}
private void setNewParam(int param) {
// double locking to prevent the calling thread from being locked
// (if in running state without pause requested then calling thread
// will be in indefinite wait state for acquiring the lock.
if (isPauseRequested) {
synchronized (lock) {
if (isPauseRequested) {
this.param = param;
this.isPauseRequested = false;
lock.notifyAll();
} else {
// logger will be used in real application
System.out.println("Need to pause first before setting a new param");
}
}
} else {
// logger will be used in real application
System.out.println("Need to pause first before setting a new param");
}
}
}
}
The testing driver code:
public class Test {
public static void main(String[] args) throws InterruptedException {
IResumable resumable = new ResumableModel(10);
resumable.requestStart();
//Current thread is Main thread
Thread.currentThread().sleep(3000); // making the main thread sleep for 3 seconds.
resumable.requestPause();
Thread.currentThread().sleep(3000); // again making the main thread sleep for 3 seconds.
resumable.resumeWithNewParam(20);
Thread.currentThread().sleep(3000); // again making the main thread sleep for 3 seconds.
resumable.requestStop();
}
}
Please provide review comments and feedback. It will help me and the people to whom I tell this approach.