So I've briefly stumbled across **Semaphores** in my programming journey and ever so recently took it upon myself to devise a program replicating that of a fast food chain. 

I'm going to try explain as best I can, please let me know in the comment section if I need to be more thorough

**The Plan:**

Have a ***producer*** and a ***consumer*** (tills and worker) So the tills take the order(Place them in a buffer, so a circular array..) and the worker processes that order(Takes orders out of the circular array)

I'm trying to implement semaphores so that when an order has been made, that specific till cannot be used until the worker has processed the order. And also use semaphores so that the officer can only take out one order at a time

**Here is the main method:**

```
public class FastFood {

    /**
     * @param args the command line arguments
     */
    static Buffer buff = new Buffer(2);
    static Semaphore semWorker = new Semaphore(1);
    static Semaphore semTills = new Semaphore(1);
    static int totalOrders = 10;
    static int startOrders = 0;
    static int processedOrders = 0;

    public static void main(String[] args) {
        // TODO code application logic here

        int numberOfWorkers = 2;
        int numberOfTills = 3;
        int numberOfFoodChoices = 4;
        Random rand = new Random();

        Tills[] tills = new Tills[numberOfTills];
        Worker[] workers = new Worker[numberOfWorkers];

        //int tillId, int foodId, Buffer buff
        for (int i = 0; i < tills.length; i++) {
            int foodId = rand.nextInt(numberOfFoodChoices) + 1;
            tills[i] = new Tills(i, foodId, buff);
            tills[i].start();
        }

        //int workerId, Buffer buff
        for (int i = 0; i < workers.length; i++) {
            workers[i] = new Worker(i, buff);
            workers[i].start();
        }

        for (Tills till : tills) {
            try {
                till.join();
            }catch (InterruptedException ex) {
                System.out.println(ex);
            }
        }

        for (Worker worker : workers) {
            try {
                worker.join();
            }catch (InterruptedException ex) {
                System.out.println(ex);
            }
        }

```

So as you can see by the main method I am looping and running the array of threads for both the worker and the tills.

Here is the tills class. So this creates the order. You will be able to see that I am using FastFood.semTills.down() and FastFood.semTills.up() this is using the semaphore. So down is acquiring the semaphore and up is releasing it. **However** the problem is my logic for the positioning of these semaphore downs and ups.

```
public class Tills extends Thread {
    private final Buffer buff;
    private final int foodId;
    private final int tillId;

    public Tills(int tillId, int foodId, Buffer buff) {
        this.tillId = tillId;
        this.foodId = foodId;
        this.buff = buff;
    }

    @Override
    public void run(){
        FastFood.semTills.down();
        while(FastFood.startOrders < FastFood.totalOrders){
            FastFood.semTills.up();
            buff.acquire(); 
            while(buff.isFull()){
                try {
                    buff.release();
                    sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Tills.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            FastFood.startOrders++;
            Order v = new Order(foodId, tillId);
            System.out.println(v.toString());            
            try {
                Random n = new Random();
                int time = n.nextInt(100) + 1;
                buff.release();
                sleep(time);
                buff.insert(v);
            } catch (InterruptedException ex) {
                System.out.println(ex);
            }

        }
    }

```

The worker class is somewhat the same, yet I want to ensure that only one worker can process a specific order at a time ( It is fine to enable multiple workers to enable multiple orders)

```
public class Worker extends Thread{
    private final int workerId;
    private final Buffer buff;

    public Worker(int workerId, Buffer buff) {
        this.workerId = workerId;
        this.buff = buff;
    }

    public void run(){
        FastFood.semWorker.down();
        while(FastFood.totalOrders>FastFood.processedOrders){
            buff.acquire();
            while(buff.isEmpty()){
                FastFood.semWorker.up();
                try {
                    buff.release();
                    sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            FastFood.processedOrders++;
            System.out.print("Worker: " + workerId);
            buff.remove();
            buff.release();
            try {
                Random n = new Random();
                int time = n.nextInt(100) + 1;
                sleep(time);
            } catch (InterruptedException ex) {
                System.out.println(ex);
            }

        }
        FastFood.semWorker.up();
    }

```

This is the output I'm getting, you can see that it is not waiting for the orders to be processed, thus the positioning of my semaphores must be wrong, I've tried all sorts of possibilities:

```
run:
FoodId: 3 TillId : 1 Order Count : 0
FoodId: 3 TillId : 0 Order Count : 1
FoodId: 4 TillId : 2 Order Count : 2
FoodId: 4 TillId : 2 Order Count : 3
FoodId: 4 TillId : 2 Order Count : 4
FoodId: 3 TillId : 0 Order Count : 5
FoodId: 3 TillId : 0 Order Count : 6
Worker: 1 Food: 3 TillId: 0
Worker: 0 Food: 3 TillId: 0
FoodId: 3 TillId : 0 Order Count : 7
FoodId: 3 TillId : 0 Order Count : 8
Worker: 1 Food: 3 TillId: 0
FoodId: 3 TillId : 0 Order Count : 9
FoodId: 3 TillId : 1 Order Count : 10
Worker: 0 Food: 3 TillId: 0
Worker: 1 Food: 3 TillId: 1
Worker: 0 Food: 3 TillId: 0
Worker: 1 Food: 4 TillId: 2
Worker: 0 Food: 3 TillId: 0
Worker: 1 Food: 4 TillId: 2
Worker: 0 Food: 3 TillId: 0
10

```

Quick Class Brief:

FastFood: Main, creates the threads
Buffer: For the circular array
Order: Stores what food from what till
Tills: Creates an order
Worker: Processes an order

Semaphore:

```
package fastfood;

public class Semaphore {

    private int count;

    public Semaphore(int n) {
        count = n;
    }

    public synchronized void down() {

        while (count == 0) {

            try {
                wait(); // Blocking call.
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
        }
        count--;
    }

    public synchronized void up() {
        count++;
        notify();
    }
}

```

Buffer:

```
public class Buffer {
    private int size;
    private int inPtr = 0;
    private int outPtr = 0;
    private int counter = 0;
    private Order[] data; 
    private Semaphore sem = new Semaphore(1);

    public Buffer(int size) {
        this.size = size;
        this.data = new Order[size];
    }

    public Order remove(){
        // removes the revote for the officer 
        Order out;
        out = data[outPtr];
        System.out.println(" Food: " + out.getFoodId() + " TillId: " + 
            out.getTillId());
        outPtr = (outPtr+1)%size;
        counter--;
        return out;
    }
    public void insert(Order i){
        // inserts a new vote 
        data[inPtr] = i;
        inPtr = (inPtr+1)%size;
        counter++;
    }
    public boolean isEmpty(){
        // returns true if empty
        return counter==0;
    }
    public boolean isFull(){
        // returns true if full
        return counter==size;
    }
    public void acquire(){
        sem.down();
    }
    public void release(){
        sem.up();
    }

}

```

CHANGES:

Change 2:

**Worker Class:**

```
public void run() {
       while(FastFood.processedOrders < FastFood.totalOrders){
           try{
                buff.acquire();
                FastFood.semWorker.down();
                while(buff.isEmpty()){
                    try {
                        sleep(100);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                try{
                Order o = buff.remove();
                System.out.println(o.toString() + " FoodId: " + o.getFoodId() 
                        + " TillId: " + o.getTillId());
                FastFood.processedOrders++;
                }catch(Exception e){
                    System.out.println(e);
                }
           }finally{
               buff.release();
               FastFood.semTills.up();
           }

       }

```

Tills Class:

```
while (FastFood.startOrders < FastFood.totalOrders) {
            try {
                buff.acquire();
                FastFood.semTills.down();
                while (buff.isFull()) {
                    try {
                        sleep(100);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Tills.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                try {
                    Order o = new Order(foodId, tillId);
                    System.out.println(o.toString());
                    buff.insert(o);
                    FastFood.startOrders++;
                } catch (Exception e) {
                    System.out.println(e);
                }
            } finally {
                buff.release();
                FastFood.semWorker.up(); 
            }

```

Order:

```
public class Order {
    private final int foodId;
    private final int tillId;
    static int count = 0;
    private int orderCount=0;

    public Order(int foodId, int tillId){
        this.foodId = foodId;
        this.tillId = tillId;
        this.orderCount = count++;
    }

    public int getFoodId() {
        return foodId;
    }

    public int getTillId() {
        return tillId;
    }

    public static int getCount() {
        return count;
    }

    public int getOrderCount() {
        return orderCount;
    }

    @Override
    public String toString() {
        return "FoodId: " +foodId+" TillId : "+tillId+" Order Count : "+ orderCount; 
    }

```