ResizableSemaphore

package education.jtrainer.javainterviewquestions;

import java.util.concurrent.Semaphore;
import java.util.Random;
/**
 *
 * @author Diego Gabriele
 */
public class ResizableSemaphore extends Semaphore{
    
    int originalPermits;
    
    public ResizableSemaphore(int permits) {
        super(permits);
        originalPermits=permits;
    }
    
    @Override
    protected void reducePermits(int reduction) {
        super.reducePermits(reduction);
    }
    
    public int usedPermits() {
        return originalPermits - availablePermits();
    }
    @Override
    public void release(int i){
        super.release(i);
    }
    
    static class MyBuyer extends Thread {

                ResizableSemaphore semaphore;            
        String name = "";
                int totalCashiers; //this is the number of the total number of cashiers allocated by the shop manager

        MyBuyer(String name, ResizableSemaphore semaphore) {
            this.name = name;
                        this.semaphore=semaphore;
        }

        public void run() {

            try {
                totalCashiers=semaphore.usedPermits()+semaphore.availablePermits();
                                System.out.println(name + ": trying to pay groceries...");
                                System.out.println(name + ": available cashiers: " + semaphore.availablePermits()+" total cashiers: "+totalCashiers);
                System.out.println(name + ": there are "+semaphore.getQueueLength() + " people in the lane waiting to pay their goods who precede me");
                                if (semaphore.getQueueLength() >=2) {
                                    System.out.println("too many people in the lane, manager will allocate  another cashier");
                                    semaphore.release(1);
                                    System.out.println("Available cashiers are now: " + semaphore.availablePermits());
                                }
                                
                                semaphore.acquire();
                                System.out.println(name + " :got the permit to pay goods!");
                                try {
                    for (int i = 1; i <= 5; i++) {
                                                totalCashiers=semaphore.usedPermits()+semaphore.availablePermits();
                        System.out.println(name + ": I am paying good n." + i + ", available cashiers: "+ semaphore.availablePermits() +" total cashiers: "+totalCashiers);
                        // sleep 5000 ms - this is the time needded to pay 
                        Thread.sleep(5000);
                    }

                } finally {
                    // calling release() after succesfully paying the groceries
                    System.out.println(name + ": releasing lock..., cashier is available now to serve a new customer");
                    semaphore.release();
                    System.out.println(name + ": available cashiers now: " + semaphore.availablePermits());
                                        
                                        // when the queue length get reduces the manager deallocates the cashier
                                        if (semaphore.getQueueLength() <=1 && semaphore.availablePermits()>2 ){
                                            semaphore.reducePermits(1);
                                            System.out.println("manager removed cashier");
                                            System.out.println(name + ": available cashiers: " + semaphore.availablePermits());
                                        }
                                
                                
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {

        System.out.println("This is the ResizableSemaphore tutorial");
                
                ResizableSemaphore semaphore=new ResizableSemaphore(2);
                
                MyBuyer t1 = new MyBuyer("Anna",semaphore);
                t1.start();
                
                Thread.sleep(new Random().nextInt(10000));
        MyBuyer t2 = new MyBuyer("Bob",semaphore);
        t2.start();

                Thread.sleep(new Random().nextInt(10000));
        MyBuyer t3 = new MyBuyer("Charlie",semaphore);
        t3.start();
                
                Thread.sleep(new Random().nextInt(10000));
        MyBuyer t4 = new MyBuyer("Don",semaphore);
        t4.start();
                
                Thread.sleep(new Random().nextInt(10000));
        MyBuyer t5 = new MyBuyer("Eric",semaphore);
        t5.start();

                Thread.sleep(new Random().nextInt(10000));
        MyBuyer t6 = new MyBuyer("Fred",semaphore);
        t6.start();
    }
}