package my.code.concurrency.c02.taskqueue;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import my.code.concurrency.c02.taskqueue.common.ITaskManager;
import my.code.concurrency.c02.taskqueue.common.Request;
import my.code.concurrency.c02.taskqueue.common.TaskManagerStatus;
import my.code.concurrency.c02.taskqueue.common.Worker;
/**
* Handle request queue and pool of worker threads to carry process requests.
* In spike times some request will have to wait.
* See readme for full assessment. Use Java < 5 concurrency features only.
*/
public class TaskManager implements ITaskManager {
/**
* Core object, the queue itself.<br>
* Linked list is a better option then ArrayList,
*/
private LinkedList<Request> jobQueue = new LinkedList<Request>();
private int numberOfWorkers = 0;
private long totalReceived;
/**
* Keep references to workers
*/
private List<Worker> workerList = new ArrayList<Worker>();
public TaskManager(int numberOfWorkers) {
this.numberOfWorkers = numberOfWorkers;
}
/**
* Client call
*
* @param request
*/
public void submit(Request request) {
synchronized (this) {
jobQueue.addLast(request);
this.notifyAll();
totalReceived++;
}
}
/**
* Workers call. Take a job from a job queue.
*/
public Request take() {
Request workItem;
synchronized (this) {
// if queue is empty - wait
while (jobQueue.isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
// return and remove first Request from the queue
workItem = jobQueue.removeFirst();
}
return workItem;
}
/**
* Start workers
*/
public void start() {
for (int i = 0; i < numberOfWorkers; i++) {
Worker worker = new Worker(this, i);
workerList.add(worker);
new Thread(worker).start();
}
}
/**
* @return status information about internal processing, queue length,
*/
public synchronized TaskManagerStatus getStatus() {
TaskManagerStatus result = new TaskManagerStatus();
double[] progress = new double[workerList.size()];
int i = 0;
for (Worker worker : workerList) {
progress[i] = worker.getProgress();
i++;
}
result.workersProgress = progress;
result.queueLength = jobQueue.size();
result.totalReceived = totalReceived;
return result;
}
}