0% found this document useful (0 votes)
6 views16 pages

Java Restaurant Ordering System

The document outlines the design and implementation of a Restaurant Food Ordering System in Java using interfaces and arrays, allowing users to select restaurants, view menus, place orders, and generate bills. It also describes a multithreaded Producer-Consumer program, first without synchronization leading to race conditions, and then with synchronization to ensure safe communication between threads. Finally, it presents a Banking Application with threads for deposit and withdrawal operations, first without synchronization and then with proper synchronization techniques.

Uploaded by

sohamghosh2967
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views16 pages

Java Restaurant Ordering System

The document outlines the design and implementation of a Restaurant Food Ordering System in Java using interfaces and arrays, allowing users to select restaurants, view menus, place orders, and generate bills. It also describes a multithreaded Producer-Consumer program, first without synchronization leading to race conditions, and then with synchronization to ensure safe communication between threads. Finally, it presents a Banking Application with threads for deposit and withdrawal operations, first without synchronization and then with proper synchronization techniques.

Uploaded by

sohamghosh2967
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Lab Exercise 9

Design and implement a menu-driven Java program to simulate a Restaurant Food


Ordering System using interfaces, arrays, and runtime polymorphism. The program
should allow users to select a restaurant, view its menu, place an order for multiple items,
generate a bill, and confirm the order - all within a loop until the user chooses to exit.

Define an interface named Restaurant that declares the following methods.


void showMenu(): Displays the list of available food items and their prices.
Object[][] placeOrder(): Allows the customer to select multiple items, specify quantities,
and returns a 2D array of order details, where each row contains [Item Name, Quantity,
Price].
double calculateBill(Object[][] orderDetails): Accepts the 2D array returned by
placeOrder() and computes the total bill amount for the customer’s order.

Implement the Restaurant interface in the following two classes.


Class Dominos displays its own customized menu, implements logic for placing orders
and returning order details in a 2D array, and implements bill calculation by summing
up the total of all selected items.
Class KFC displays its own customized menu, allows users to select multiple items and
specify their quantities, returns order details as a 2D array, and computes the total bill
accordingly.

Main Class: FoodOrderingSystem.


Display a main menu with the following options:

1. Order from Dominos


2. Order from KFC
3. Exit
Enter your choice.

Based on the user’s choice, display the restaurant’s menu using showMenu(), call the
placeOrder() method to accept order details and store them in a 2D array, pass this array
to calculateBill() to compute the total bill, and display the generated bill to the user. Ask
for confirmation whether the user wants to confirm or cancel the order. If confirmed,
display an order success message. If canceled, discard the order and return to the main
menu. Ensure that after every operation, the main menu reappears. The program should
continue running until the user chooses the Exit option.

Additional Requirements: Use only arrays for managing menus and order details (avoid
ArrayList, Map, or Collections). Demonstrate runtime polymorphism by invoking
methods using a Restaurant reference variable.
/**************************************************************************

50
This program has been developed by Soham Ghosh (231B341)
**************************************************************************/
import [Link];

interface Restaurant {
void showMenu();
Object[][] placeOrder();
double calculateBill(Object[][] orderDetails);
}

class Dominos implements Restaurant {


String[] items = {"Margherita", "Farmhouse", "Peppy Paneer", "Veg Extravaganza"};
double[] prices = {200, 300, 350, 400};
Scanner sc = new Scanner([Link]);

public void showMenu() {


[Link]("---- DOMINOS MENU ----");
for (int i = 0; i < [Link]; i++) {
[Link]((i + 1) + ". " + items[i] + " - Rs. " + prices[i]);
}
}

public Object[][] placeOrder() {


[Link]("Enter number of items to order: ");
int n = [Link]();
Object[][] order = new Object[n][3];
for (int i = 0; i < n; i++) {
[Link]("Enter item number: ");
int itemNo = [Link]();
[Link]("Enter quantity: ");
int qty = [Link]();
order[i][0] = items[itemNo - 1];
order[i][1] = qty;
order[i][2] = prices[itemNo - 1];
}
return order;
}

public double calculateBill(Object[][] orderDetails) {


double total = 0;
for (int i = 0; i < [Link]; i++) {
int qty = (int) orderDetails[i][1];
double price = (double) orderDetails[i][2];
total += qty * price;

51
}
return total;
}
}

class KFC implements Restaurant {


String[] items = {"Zinger Burger", "Popcorn Chicken", "Chicken Bucket", "Crispy
Strips"};
double[] prices = {180, 220, 500, 250};
Scanner sc = new Scanner([Link]);

public void showMenu() {


[Link]("---- KFC MENU ----");
for (int i = 0; i < [Link]; i++) {
[Link]((i + 1) + ". " + items[i] + " - Rs. " + prices[i]);
}
}

public Object[][] placeOrder() {


[Link]("Enter number of items to order: ");
int n = [Link]();
Object[][] order = new Object[n][3];
for (int i = 0; i < n; i++) {
[Link]("Enter item number: ");
int itemNo = [Link]();
[Link]("Enter quantity: ");
int qty = [Link]();
order[i][0] = items[itemNo - 1];
order[i][1] = qty;
order[i][2] = prices[itemNo - 1];
}
return order;
}

public double calculateBill(Object[][] orderDetails) {


double total = 0;
for (int i = 0; i < [Link]; i++) {
int qty = (int) orderDetails[i][1];
double price = (double) orderDetails[i][2];
total += qty * price;
}
return total;
}
}

52
public class FoodOrderingSystem {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
while (true) {
[Link]("\n--- FOOD ORDERING SYSTEM ---");
[Link]("1. Order from Dominos");
[Link]("2. Order from KFC");
[Link]("3. Exit");
[Link]("Enter your choice: ");
int choice = [Link]();

Restaurant r = null;
if (choice == 1) {
r = new Dominos();
} else if (choice == 2) {
r = new KFC();
} else if (choice == 3) {
[Link]("Thank you! Visit again.");
break;
} else {
[Link]("Invalid choice!");
continue;
}

[Link]();
Object[][] order = [Link]();
double total = [Link](order);
[Link]("\n--- BILL DETAILS ---");
for (int i = 0; i < [Link]; i++) {
[Link](order[i][0] + " x " + order[i][1] + " = Rs. " + ((int) order[i][1] *
(double) order[i][2]));
}
[Link]("Total Bill: Rs. " + total);
[Link]("Confirm order? (yes/no): ");
String confirm = [Link]();
if ([Link]("yes")) {
[Link]("Order confirmed! Thank you for ordering.");
} else {
[Link]("Order cancelled.");
}
}
[Link]();
}

53
}
Output :

54
Lab Exercise 10

1. Design and implement a multithreaded Producer-Consumer program in Java where


multiple Producer threads generate random integers and insert them into a shared
bounded buffer, and multiple Consumer threads remove and process these integers. You
must implement this system without using any form of synchronization. All Producers
should keep adding values to the shared buffer asynchronously, and all Consumers
should keep removing values from the buffer asynchronously. After running your
program, observe the incorrect behavior that occurs. Finally, comment on the output,
explaining why the absence of proper thread coordination leads to unpredictable and
erroneous results.

/**************************************************************************
This program has been developed by Soham Ghosh (231B341)
**************************************************************************/
import [Link];
import [Link];
import [Link];

class BoundedBuffer {
private final List<Integer> buffer = new ArrayList<>();
private final int capacity;

public BoundedBuffer(int capacity) {


[Link] = capacity;
}

public void add(int value) {


if ([Link]() < capacity) [Link](value);
}

public Integer remove() {


if ([Link]() > 0) return [Link](0);
return null;
}

public int size() {


return [Link]();
}
}

class Producer implements Runnable {


private final BoundedBuffer buffer;

55
private final Random random = new Random();

public Producer(BoundedBuffer buffer) {


[Link] = buffer;
}

public void run() {


while (true) {
int val = [Link](100);
[Link](val);
[Link]("Producer " + [Link]().getId() + " added " + val + "
| buffer size: " + [Link]());
}
}
}

class Consumer implements Runnable {


private final BoundedBuffer buffer;

public Consumer(BoundedBuffer buffer) {


[Link] = buffer;
}

public void run() {


while (true) {
Integer val = [Link]();
[Link]("Consumer " + [Link]().getId() + " removed " + val
+ " | buffer size: " + [Link]());
}
}
}

public class Main {


public static void main(String[] args) {
BoundedBuffer buffer = new BoundedBuffer(10);

for (int i = 0; i < 3; i++) {


new Thread(new Producer(buffer)).start();
}
for (int i = 0; i < 3; i++) {
new Thread(new Consumer(buffer)).start();
}
}
}

56
Output :

Explanation :-
1. Race Conditions
Multiple threads access and modify the shared buffer simultaneously, causing unpredictable
interleaving of operations.
2. Non-atomic Operations
Checking size, adding, and removing are not atomic, so their results get overwritten or
corrupted by other threads.
3. Inconsistent Buffer State
The buffer may appear full, empty, or beyond capacity incorrectly because updates clash.
4. Unpredictable Output
Consumers may remove null values, Producers may add when the buffer is full, and printed
buffer sizes become incorrect.
5. Root Cause
Lack of synchronization means the threads do not coordinate, leading to erroneous and
inconsistent behavior.

2. Design and implement a multithreaded Producer-Consumer system in Java where a


shared bounded buffer is accessed by multiple Producer threads and multiple Consumer
threads. Each Producer thread should continuously generate random integers and
attempt to insert them into the shared buffer, while each Consumer thread should
continuously remove and process these integers. To correctly coordinate the Producer
and Consumer threads, you must use proper thread synchronization mechanisms,
including: ● wait() ● notify() or notifyAll() ● synchronized methods or synchronized
blocks Your implementation must ensure that: A. A Producer must wait when the buffer
is full, and resume only when space becomes available. B. A Consumer must wait when
the buffer is empty, and resume only when new items are produced. C. No data is lost,
corrupted, overwritten, or accessed out of bounds. D. Multiple Producers and Consumers
operate correctly in parallel. Introduce a small random delay inside both Producer and

57
Consumer threads to simulate asynchronous real-world processing. After implementing
the synchronized version, observe and comment on the proper, stable output, explaining
how using wait(), notify(), and synchronized ensures safe communication between threads
and prevents issues like buffer overflow, underflow, race conditions, inconsistent data,
and thread interference.

/**************************************************************************
This program has been developed by Soham Ghosh (231B341)
**************************************************************************/
import [Link];
import [Link];

class BoundedBuffer {
private final LinkedList<Integer> buffer = new LinkedList<>();
private final int capacity;

public BoundedBuffer(int capacity) {


[Link] = capacity;
}

public synchronized void add(int value) throws InterruptedException {


while ([Link]() == capacity) {
wait();
}
[Link](value);
[Link]("Producer " + [Link]().getId() + " added " + value + "
| size=" + [Link]());
notifyAll();
}

public synchronized int remove() throws InterruptedException {


while ([Link]()) {
wait();
}
int value = [Link]();
[Link]("Consumer " + [Link]().getId() + " removed " + value
+ " | size=" + [Link]());
notifyAll();
return value;
}
}

class Producer implements Runnable {

58
private final BoundedBuffer buffer;
private final Random rand = new Random();

public Producer(BoundedBuffer buffer) {


[Link] = buffer;
}

public void run() {


try {
while (true) {
int v = [Link](100);
[Link](v);
[Link]([Link](200));
}
} catch (Exception e) {}
}
}

class Consumer implements Runnable {


private final BoundedBuffer buffer;
private final Random rand = new Random();

public Consumer(BoundedBuffer buffer) {


[Link] = buffer;
}

public void run() {


try {
while (true) {
[Link]();
[Link]([Link](200));
}
} catch (Exception e) {}
}
}

public class Main {


public static void main(String[] args) {
BoundedBuffer buffer = new BoundedBuffer(5);

for (int i = 0; i < 3; i++) new Thread(new Producer(buffer)).start();


for (int i = 0; i < 3; i++) new Thread(new Consumer(buffer)).start();
}
}

59
Output :

3. Design and implement a multithreaded Banking Application where two or more


Customer threads perform deposit and withdrawal operations on a shared bank account
without using any synchronization techniques.
Create a class BankAccount containing:
● a private integer balance,
● a deposit() method that increases the balance and prints the updated balance,
● a withdraw() method that decreases the balance if sufficient funds exist,
otherwise prints an “Insufficient Balance” message.
Next, create two thread classes:
● Depositor that repeatedly calls the deposit() method,
● Withdrawer that repeatedly calls the withdraw() method.
Both threads must operate on the same shared BankAccount object. Each operation
should run inside a loop to simulate multiple transactions.
Finally, write the main class to create a single BankAccount object and start multiple
Depositor and Withdrawer threads to operate on it simultaneously without
synchronization. After observing the output, comment on possible issues.
/**************************************************************************
This program has been developed by Soham Ghosh (231B341)
**************************************************************************/
class BankAccount {
private int balance;

public BankAccount(int balance) {


[Link] = balance;
}

public void deposit(int amount) {


balance += amount;
[Link]("Deposited " + amount + " | Balance: " + balance);

60
}

public void withdraw(int amount) {


if (balance >= amount) {
balance -= amount;
[Link]("Withdrew " + amount + " | Balance: " + balance);
} else {
[Link]("Insufficient Balance for withdrawal of " + amount + " | Balance: "
+ balance);
}
}
}

class Depositor extends Thread {


private final BankAccount account;

public Depositor(BankAccount account) {


[Link] = account;
}

public void run() {


for (int i = 0; i < 20; i++) {
[Link](50);
try { [Link](50); } catch (Exception e) {}
}
}
}

class Withdrawer extends Thread {


private final BankAccount account;

public Withdrawer(BankAccount account) {


[Link] = account;
}

public void run() {


for (int i = 0; i < 20; i++) {
[Link](30);
try { [Link](50); } catch (Exception e) {}
}
}
}

public class p3_Main {

61
public static void main(String[] args) {
BankAccount account = new BankAccount(100);

Thread d1 = new Depositor(account);


Thread d2 = new Depositor(account);
Thread w1 = new Withdrawer(account);
Thread w2 = new Withdrawer(account);

[Link]();
[Link]();
[Link]();
[Link]();
}
}

Output :

4. Design and implement a multithreaded Banking Application in Java where one thread
acts as a Depositor and another thread acts as a Withdrawer, both working on the same
shared BankAccount object. The Depositor thread should repeatedly deposit a fixed
amount into the account, and the Withdrawer thread should repeatedly attempt to
withdraw the same amount.
In this version, you must use proper synchronization to ensure consistent and
predictable updates to the account balance. You are required to use:
● synchronized methods or synchronized blocks
● wait() and notify() / notifyAll() for thread communication
The Depositor must wait if the balance has reached a specified maximum limit, and the
Withdrawer must wait if the balance becomes zero. When the state changes (after deposit
or withdrawal), appropriate threads should be notified.

62
After implementing the program, run it multiple times to observe the stable and correct
behavior such as no underflow, no over-withdrawal, no race conditions, and proper
alternation between deposit and withdrawal. Finally, comment on how synchronization
ensures safe access to shared data and prevents inconsistent states.
/**************************************************************************
This program has been developed by Soham Ghosh (231B341)
**************************************************************************/
class BankAccount {
private int balance;
private final int maxLimit;

public BankAccount(int balance, int maxLimit) {


[Link] = balance;
[Link] = maxLimit;
}

public synchronized void deposit(int amount) throws InterruptedException {


while (balance + amount > maxLimit) {
wait();
}
balance += amount;
[Link]("Deposited " + amount + " | Balance: " + balance);
notifyAll();
}

public synchronized void withdraw(int amount) throws InterruptedException {


while (balance < amount) {
wait();
}
balance -= amount;
[Link]("Withdrew " + amount + " | Balance: " + balance);
notifyAll();
}
}

class Depositor extends Thread {


private final BankAccount account;
private final int amount;

public Depositor(BankAccount account, int amount) {


[Link] = account;
[Link] = amount;
}

63
public void run() {
try {
while (true) {
[Link](amount);
[Link](100);
}
} catch (Exception e) {}
}
}

class Withdrawer extends Thread {


private final BankAccount account;
private final int amount;

public Withdrawer(BankAccount account, int amount) {


[Link] = account;
[Link] = amount;
}

public void run() {


try {
while (true) {
[Link](amount);
[Link](100);
}
} catch (Exception e) {}
}
}

public class Main {


public static void main(String[] args) {
BankAccount account = new BankAccount(0, 200);

Thread depositor = new Depositor(account, 50);


Thread withdrawer = new Withdrawer(account, 50);

[Link]();
[Link]();
}
}

Output :

64
Synchronization makes sure only one thread accesses the shared balance at a time, preventing
race conditions.
Using wait() and notifyAll() forces threads to pause when the balance is too high or too low,
avoiding overflow and underflow.
Together, these mechanisms ensure that deposits and withdrawals happen in a controlled,
orderly way, keeping the account balance consistent and preventing corrupted or unpredictable
states.

65

You might also like