
Java Assignment Solution on Synchronization Primitives
- 22nd Jul, 2022
- 15:45 PM
import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; public class Main { private static final int CLIENTS_NUM = 100; private static final int TELLERS_NUM = 3; private static final int SAFE_TELLERS_ACCESS = 2; private static final Semaphore safe = new Semaphore(SAFE_TELLERS_ACCESS); private static final Queue clientLine = new ConcurrentLinkedQueue<>(); public static void main(String[] args) { for (int i = 0; i < CLIENTS_NUM; i++) { Client client = new Client(i); client.start(); } List tellers = new ArrayList<>(); for (int i = 0; i < TELLERS_NUM; i++) { Teller teller = new Teller(i); tellers.add(teller); teller.start(); } try { for (Teller teller : tellers) { teller.join(); } } catch (InterruptedException exception) { exception.printStackTrace(); } System.out.println("Bank closes"); } static class Client extends Thread { private final int clientId; private ClientOperation clientOperation; Client(int clientId) { this.clientId = clientId; } public int getClientId() { return clientId; } public ClientOperation getClientOperation() { return clientOperation; } public synchronized void setTeller(Teller teller) { System.out.println(MessageFormat.format("Client {0} goes to Teller {1}", clientId, teller.getTellerId())); notify(); } public synchronized void startProcessing() { System.out.println(MessageFormat.format("Client {0} wants to make a {1}", clientId, clientOperation)); notify(); } public synchronized void finishProcessing() { System.out.println(MessageFormat.format("Client {0} is done", clientId)); notify(); } public synchronized void finishServing() { System.out.println(MessageFormat.format("Client {0} leaves", clientId)); notify(); } @Override public synchronized void run() { try { if (new Random().nextBoolean()) { clientOperation = ClientOperation.Deposit; } else { clientOperation = ClientOperation.Withdraw; } clientLine.add(this); System.out.println(MessageFormat.format("Client {0} waits in line to make a {1}", clientId, clientOperation)); // waiting for some teller to start servicing wait(); // waiting for teller to start processing wait(); // waiting for teller to finish processing wait(); // wainting for teller to finish servicing wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } enum ClientOperation { Deposit, Withdraw } static class Teller extends Thread { private final int tellerId; Teller(int tellerId) { this.tellerId = tellerId; } public int getTellerId() { return tellerId; } @Override public void run() { System.out.println(MessageFormat.format("Teller {0} is available", tellerId)); Client client; while ((client = clientLine.poll()) != null) { try { client.setTeller(this); int clientId = client.getClientId(); System.out.println(MessageFormat.format("Teller {0} is serving Client {1}", tellerId, clientId)); client.startProcessing(); ClientOperation clientOperation = client.getClientOperation(); System.out.println(MessageFormat.format("Teller {0} is processing Client {1}''s {2}", tellerId, clientId, clientOperation)); if (clientOperation == ClientOperation.Withdraw) { System.out.println(MessageFormat.format("Teller {0} is getting the manager's approval", tellerId)); long managersApprovalTime = new Random().nextInt(251) + 50; Thread.sleep(managersApprovalTime); System.out.println(MessageFormat.format("Teller {0} is got the manager's approval", tellerId)); } long useSafeTime = new Random().nextInt(401) + 100; System.out.println(MessageFormat.format("Teller {0} is going to the safe", tellerId)); Thread.sleep(useSafeTime); safe.acquire(); System.out.println(MessageFormat.format("Teller {0} is using the safe", tellerId)); safe.release(); System.out.println(MessageFormat.format("Teller {0} is done using the safe", tellerId)); System.out.println(MessageFormat.format("Teller {0} notifies Client {1}", tellerId, clientId)); client.finishProcessing(); System.out.println(MessageFormat.format("Teller {0} has finished serving Client {1}", tellerId, clientId)); client.finishServing(); System.out.println(MessageFormat.format("Teller {0} is available", tellerId)); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(MessageFormat.format("Teller {0} Closes", tellerId)); } } }