I have to simulate the activity of a postal office, where an office worker can offer many services like paying bills, send letters etc. I have created a separate application which simulates the incoming clients and store them in the database. The second application has to manage the "clients" from the database and assign to each office worker "clients" that have requested specific tasks. If the office worker is busy then the client should be added in a waiting queue. Each office worker should do the job in a new thread. The problem is that when i run the application only one thread is doing his job. Then the application stops. Anyone has any suggestions on how can i implement this application using multithreading?
Office worker class
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import ro.csm.database_access.OperationDatabaseAccess;
import ro.csm.database_access.TaskDatabaseAccess;
public class OfficeWorker {
//each office worker has a queue of tasks, a list of supported operations, an office and a thread
private Queue<Task> tasks;
private List<Operation> supportedOperations;
private Thread workingThread;
private Office office;
//constructor
public OfficeWorker(Office office){
this.office = office;
supportedOperations = OperationDatabaseAccess.getAllSupportedOperations(office.getId());
workingThread = new Thread();
workingThread.start();
setTasks(new LinkedList<Task>());
}
//add task to the tasks queue
public void addTask(Task task){
getTasks().add(task);
}
//finish the task
public void work(){
while(true){
Task t = getTasks().poll();
if(t != null){
TaskDatabaseAccess.setTaskCompleted(t.getId());
try {
Thread.sleep(getCompletionTime(t));
workingThread.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//generate a random completion time for each task considering the minimum time and the maximum time allocated for a task
private int getCompletionTime(Task t){
Operation op = OperationDatabaseAccess.getOperationByTaskId(t.getId());
int min = op.getMinTime();
int max = op.getMaxTime();
Random rand = new Random();
return rand.nextInt(max - min + 1) - min;
}
Main application class
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import ro.csm.database_access.OfficeDatabaseAccess;
import ro.csm.database_access.OperationDatabaseAccess;
import ro.csm.database_access.TaskDatabaseAccess;
import ro.csm.models.Office;
import ro.csm.models.OfficeWorker;
import ro.csm.models.Operation;
import ro.csm.models.Task;
public class MainApplication {
//list of available offices
static List<Office> offices = OfficeDatabaseAccess.getOffices();
//list of office workers
static List<OfficeWorker> workers = createOfficeWorker(offices);
public static void main(String[] args) {
while(true){
//get the list of pending tasks
List<Task> tasks = TaskDatabaseAccess.getNotStarted();
for(Task t : tasks){
//for each task set the status in progress
TaskDatabaseAccess.setTaskInProgres(t.getId());
//assign the task to a office worker
assignTaskToOfficeWorker(t);
}
}
}
public static void assignTaskToOfficeWorker(Task t){
//create a list of possible workers
List<OfficeWorker> possibleWorkers = new ArrayList<OfficeWorker>();
//get the supported operations for each office worker
for(OfficeWorker ow : getWorkers()){
List<Operation> supportedOperations = OperationDatabaseAccess.getAllSupportedOperations(ow.getOffice().getId());
//check if the given task is in the list of supported operations
for(Operation op : supportedOperations){
if(op.getId() == t.getIdOperation()){
//if the task can be executed by this office worker then add this worker in the list of possible workers
possibleWorkers.add(ow);
}
}
}
//assign the task to the worker that has the smallest queue tasks
OfficeWorker toBeAssigned = findOWMinTaskInQueue(possibleWorkers);
toBeAssigned.addTask(t);
//update the task with the office number
TaskDatabaseAccess.updateTaskWithOfficeInformation(toBeAssigned.getOffice().getId(), t.getId());
//complete the task
toBeAssigned.work();
}
public static List<OfficeWorker> createOfficeWorker(List<Office> offices){
List<OfficeWorker> workers = new ArrayList<OfficeWorker>();
for(Office office : offices){
OfficeWorker ow = new OfficeWorker(office);
workers.add(ow);
}
return workers;
}
public static OfficeWorker findOWMinTaskInQueue(List<OfficeWorker> workers){
Collections.sort(workers, new Comparator<OfficeWorker>() {
public int compare(final OfficeWorker ow1, final OfficeWorker ow2){
return ((Integer) ow1.getTasks().size()).compareTo((Integer)ow2.getTasks().size());
}
});
return workers.get(0);
}
stop()method of Thread. It has been deprecated for over 15 years now, for good reason, as it can compromise thread safety (including in objects you aren't managing). Always write your Runnable to gracefully exit when receiving an interrupt, and then have your other code stop the Thread by interrupting it.