The following Java code is incomplete, you can solve all of the problems above b
ID: 3805969 • Letter: T
Question
The following Java code is incomplete, you can solve all of the problems above by only making changes to two files: WorkerActivityDriver.java and OrderQueue.java, edit it to meet the requirements of the activity:
------------------------------------------------
Activity Info:
This java code involves one taskmaster thread and several worker threads. The taskmaster thread creates new tasks and adds them to the order queue. Each task takes a certain number of milliseconds to complete. The worker threads pick up tasks from the order queue and simulate working on them by sleeping for the specified number of milliseconds. The program continues until a total of 100 tasks have been created.
-------------------------------------------
Requirements:
• Right now the queue can behave inconsistently. For example, occasionally two workers can both accept the same task (see below). Modify the program so that this cannot occur.
Worker 3 accepted Task 1: 1007 ms
Worker 1 accepted Task 2: 896 ms
Worker 2 accepted Task 1: 1007 ms
• Right now the program can say it is finished before all of the tasks have been made and completed (see below). Modify the program so that this cannot occur.
Worker 1 accepted Task 1: 1175 ms
Finished?
Worker 1 finished Task 1: 1175 ms
• Right now if a worker requests a task to work on but the queue is empty, the acceptTask method will loop until the queue is no longer empty, as shown below. This is called a “busy loop” and it is not an efficient use of CPU time. Modify this code so that the method instead waits until it has been notified that a new task has been created.
public Task acceptTask() {
while (orders.isEmpty()) {
// looping until there is a task in the queue
}
return orders.poll();
}
• Change the program so that if there are five tasks in the queue, the program will wait until the number of tasks falls below five before adding any more tasks to the queue.
--------------------------------------------------------------------------
Provided Code:
public class WorkerActivityDriver {
public static void main(String[] args) throws Exception {
OrderQueue orders = new OrderQueue();
Thread tm = new Thread(new TaskMaster(orders));
Thread w1 = new Thread(new Worker(orders, 1));
Thread w2 = new Thread(new Worker(orders, 2));
Thread w3 = new Thread(new Worker(orders, 3));
tm.start();
w1.start();
w2.start();
w3.start();
System.out.println("Finished?");
}
}
---------------------------------------------------------
class OrderQueue {
private Queue<Task> orders;
private boolean moreOrdersComing;
public OrderQueue() {
orders = new ArrayDeque<>();
moreOrdersComing = true;
}
public void createTask(String label, int timeToComplete) {
orders.offer(new Task(label, timeToComplete));
}
public Task acceptTask() {
while (orders.isEmpty()) {
// looping until there is a task in the queue to accept
}
return orders.poll();
}
public void setNoMoreOrders() {
moreOrdersComing = false;
}
public boolean weAreDone() {
return orders.isEmpty() && !moreOrdersComing;
}
}
-------------------------------------------------------------
class Task {
private String label;
private int timeToComplete;
public Task(String label, int timeToComplete) {
this.label = label;
this.timeToComplete = timeToComplete;
}
public int getTimeToComplete() {
return timeToComplete;
}
@Override
public String toString() {
return label + ": " + timeToComplete + " ms";
}
}
-----------------------------------------------------------
class TaskMaster implements Runnable {
private final OrderQueue orders;
private int ordersCreated;
public TaskMaster(OrderQueue orders) {
this.orders = orders;
this.ordersCreated = 0;
}
@Override
public void run() {
while (ordersCreated++ < 100) {
String orderLabel = "Task " + ordersCreated;
int orderTime = (int) (Math.random() * 1000 + 250);
orders.createTask(orderLabel, orderTime);
}
orders.setNoMoreOrders();
}
}
------------------------------------------------------
class Worker implements Runnable {
private final OrderQueue orders;
private final int workerId;
public Worker(OrderQueue orders, int workerId) {
this.orders = orders;
this.workerId = workerId;
}
@Override
public void run() {
while (!orders.weAreDone()) {
Task task = orders.acceptTask();
System.out.println("Worker " + workerId + " accepted " + task);
try {
Thread.sleep(task.getTimeToComplete());
} catch (InterruptedException e) {
System.out.println("Worker " + workerId +
" failed to complete " + task);
}
//System.out.println("Worker " + workerId + " finished " + task);
}
}
}
Explanation / Answer
Req - 1
In order to make the worker thread take unique tasks. you will have to make the OrderQueue.acceptTask() method synchrinized. So That two method does not access the method at the same time.
public synchronized Task acceptTask() {
// code body
}
#################################################################
Req - 2
"Finished" should print only after all the worket and taskMaster thread dies. Hence use Thread.join() which returns when Thread dies. Hence Main will join after all thread dies.
public class WorkerActivityDriver {
public static void main(String[] args) throws Exception {
OrderQueue orders = new OrderQueue();
Thread tm = new Thread(new TaskMaster(orders));
Thread w1 = new Thread(new Worker(orders, 1));
Thread w2 = new Thread(new Worker(orders, 2));
Thread w3 = new Thread(new Worker(orders, 3));
tm.start();
w1.start();
w2.start();
w3.start();
// Code for Req 2 - Start
tm.join();
w1.join();
w2.join();
w3.join();
// Code for Req 2 - Start
System.out.println("Finished?");
}
}
#################################################################
Req - 3
For this req you will have to use Thread.wait() to make it efficient
#################################################################
Req -4
Add field "size" in OrderQueue to keep track the current size -------------
class OrderQueue {
private Queue<Task> orders;
private boolean moreOrdersComing;
private int size;
public OrderQueue() {
orders = new ArrayDeque<>();
moreOrdersComing = true;
this.size = 0;
}
public void createTask(String label, int timeToComplete) {
orders.offer(new Task(label, timeToComplete));
}
public synchronized Task acceptTask() {
while (orders.isEmpty()) {
// looping until there is a task in the queue to accept
}
this.size--;
return orders.poll();
}
public void setNoMoreOrders() {
moreOrdersComing = false;
}
public boolean weAreDone() {
return orders.isEmpty() && !moreOrdersComing;
}
public int getSize() {
return this.size;
}
}
Add this extra condition in TaskMaster.run() method
while (ordersCreated++ < 100 && orders.getSize() <= 5) {
// while body
}