0

I'm trying to use Java to simulate a set of Checkout counters in a shopping center.

This is the assumption. There are 5 checkout counters. Like a real shopping center there is a line at each counter. Each counter services one customer at a time.

I tried to implement this as follows:

  1. Each customer is a class that runs a thread similar to the producer in the producer-consumer problem. The customers are part of a blockingqueue. I will somehow need a set of blocking queues to simulate 5 lines in front of the 5 checkout counters. How do I achieve this.

  2. The checkout counters have been defined as an Single thread Executor service. So now there will be 5 executors that will service one (producer) thread at a time. I have defined an arraylist of executors to simulate this group of 5.

  3. At the counter, one thread at a time from it's corresponding queue is being executed by the executor service (i.e consumer is consuming what the producer produces).

Is my logic correct?

I have some code but I'm not sure if my logic has been executed correctly by this code.

Please help. Cheers..

Code:

Checkout.java

package Supermarket;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Checkout implements Runnable
{
    public BlockingQueue<Integer> item_queue = new ArrayBlockingQueue<Integer>(10);

    public int checkout_number;
    public int item;

    public Random random;

    public Checkout(int checkout_number, BlockingQueue<Integer> item_queue)
    {
        this.checkout_number = checkout_number;
        this.item_queue = item_queue;

        random = new Random();
        System.out.println("\nCheckout Counter Number: "+checkout_number);
    }

    public void run()
    {
        while(true)
        {           
            if(item == -1)
            {
                System.out.println("Consumer finished");
                break;
            }
            else
            {
                try 
                {
                    item = item_queue.take();
                } 
                catch (InterruptedException e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                System.out.println("\nConsumer has taken item ==> "+item);
                System.out.println("Scanning item");

                try 
                {
                    Thread.sleep(random.nextInt(5000));
                } 
                catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

}

Customer.java

    package Supermarket;

import java.util.*;
import java.util.concurrent.*;

public class Customer implements Runnable
{

    public int item;
    public int customer_number;
    public int i;
    public int item_count;

    public Random random = new Random();
    public BlockingQueue<Integer> item_queue = new ArrayBlockingQueue<Integer>(10);

    public Customer(int customer_number, BlockingQueue<Integer> item_queue)
    {
        this.customer_number = customer_number;
        this.item_queue = item_queue;
    }

    public void run()
    {
        item_count = random.nextInt(5);

        System.out.println("I am customer Number: "+customer_number+" and I have "+item_count+" items");

        for(i=0; i<item_count; i++)
        {
            try 
            {
                item_queue.put(random.nextInt(10));
            } 
            catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try 
        {
            item_queue.put(-1);
        } 
        catch (InterruptedException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Driver.java

package Supermarket;

import java.util.concurrent.*;
import java.util.*;

public class Driver 
{
    public static BlockingQueue<Integer> item_queue = new ArrayBlockingQueue<Integer>(10);

    public static Random random = new Random();

    public static int customer_count;
    public static int checkout_count;
    public static int i;

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        customer_count = random.nextInt(4)+1;
//      checkout_count = 5;

        System.out.println("Total Number of Customers: "+customer_count+"\n");

            for(i=0; i<customer_count; i++)
            {
                Customer customer = new Customer(i+1, item_queue);
                Thread customer_thread = new Thread(customer);
                customer_thread.start();
            }

//          for(i=0; i<=checkout_count; i++)
//          {
//              Checkout checkout = new Checkout(1, item_queue);
//              Thread checkout_thread = new Thread(checkout);
//              checkout_thread.start();
//          }

//      System.out.println("\n\nProgram Terminates!\n\n");
    }

}
james
  • 131
  • 9
  • Are we talking about a checkout counter, where each counter has their own line? Or are we talking about a checkout counter where there is a long line of people waiting, and people are called forward once a checkout counter becomes available? – Mark Oct 19 '18 at 10:48
  • Each counter has it's own line. – james Oct 19 '18 at 10:51
  • Welcome to SO. So each checkout has its own `BlockingQueue` . Sounds good to me. You'll need a class to randomly add customers to those queues, and I guess set random different processing time to each customer. – c0der Oct 19 '18 at 12:46
  • Hi @c0der .. thank you. I updated the code. Can you check it out and let me know if my logic so far for one checkout counter is correct? Also could you tell me if my requirement would just mean that I have to execute the same logic in a loop for n checkout counters? Thanks :) – james Oct 19 '18 at 18:51
  • Question here are typically related to problem solving. Please test your code and post [mcve] when you have question about specific issues. – c0der Oct 20 '18 at 09:51

2 Answers2

0

Your simulation may need to consider a few more features. For example you may want to consider some or all of the following design considerations:

Customer

Each customer has the following characteristics

  • A set of items to purchase.
    • All items are purchased in a single transaction, not one at a time
    • There may be 0..* items in a single transaction.
    • A 0-item transaction results in a receipt of $0.00.
  • Customer identification
  • Time of arrival at checkout line
  • Time of completed checkout transaction
  • Value of purchase transaction (i.e. a receipt)

Checkout counter

Each checkout counter has the following characteristics

  • A queue for customers waiting to check out.

  • The queue may have 0..* customers waiting to check out

  • The count of customers in a queue is available to each customer before entering the queue

  • Customers always choose the shortest available checkout queue

  • Once in a checkout queue all customers stay in that queue until their transaction is serviced.

  • Checkout Counter ID

  • A tally of customers served since the store opened

    • A 0 item transaction does not increment the tally of customers served
  • A total of all sales handled by the checkout counter

Store Inventory

The set of items available to purchase is the store inventory. Each item has the following characteristics

  • Item Id

  • Item cost

The set of items a customer acquires to purchase contains only the Item ID for each item. A particular Item ID may appear more than once in a list of items a customer chooses to purchase.

Jim Rogers
  • 4,822
  • 1
  • 11
  • 24
-1

My logic would be as follows:

  1. Write the checkout counter as it's own thread
  2. Write the line (line of customers) as normal list. It would not have to be a BlockingDeque since each checkout counter handles it's own line.

This way it will work like a real supermarket, each checkout counter handles their own line.

Based on this I think writing the code should be more logical.

Mark
  • 5,089
  • 2
  • 20
  • 31
  • Hi mark .. thank you. I updated the code. Can you check it out and let me know if my logic so far for one checkout counter is correct? Also could you tell me if my requirement would just mean that I have to execute the same logic in a loop for n checkout counters? Thanks :) – james Oct 19 '18 at 18:51
  • Code looks good, I haven't run it myself though. And yes I would just make an array of n amount of checkout counters and start the threads for each counter. That way each counter is doing their own thing while others are doing theirs! – Mark Oct 20 '18 at 14:31