I
I
Ilya Balabanov2015-10-14 23:32:59
Java
Ilya Balabanov, 2015-10-14 23:32:59

How to implement JAVA simulation using multithreading?

Good day :) I'm trying to master multithreading, working on a kind of shopping center simulator in text mode, without GUI implementation. In general, there are 20 cash desks for example and 1000 buyers. Each buyer has some purchases in the basket (random number from 1-20). Depending on how many items the buyer has, the flow will have a different execution time. Something like this. It looks like this, it seems to me:
Checkout X is working...
Customer Y has Z items.
Etc. I will be glad to any advice. Confused about the implementation of the concept.
What happened to write.

ExecutorService executor = Executors.newFixedThreadPool(21);
        for (int i = 1; i < 21; i++) {
            CustomNumber n = new CustomNumber(2000,i);
            System.out.println("Касса номер " + i + ":");
            executor.submit(n);
        }
        executor.shutdown();
        try {
            executor.awaitTermination(20, TimeUnit.SECONDS);
        } catch (InterruptedException ex) {
            Logger.getLogger(Threads1.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Все покупатели обслужены.");

public class CustomNumber implements Runnable {

    private int number;
    private int thread;

    public CustomNumber(int number, int thread) {
        this.number = number;
        this.thread = thread;
    }

    public void run() {
        int items = (int)(Math.random()*20+1);
        System.out.println(thread + ": " + items);
    }

}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
pi314, 2015-10-17
@ilyablbnv

At the request of viewers :)

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class Simulation {

  private static final Random globalRandom = new Random(System.currentTimeMillis());
  
  public synchronized int getRandomIntInRangeEnclosed(int min, int max){
    return globalRandom.nextInt((max - min + 1) + min);
  }
  
  private final static int CUSTOMER_NUMBER = 3000;
  private final static int DESK_NUMBER = 6;

  public final int ITEM_DURATION_S_MIN = 3;
  public final int ITEM_DURATION_S_MAX = 8;

  public final CustomerFactory customerFactory = new CustomerFactory(this, CUSTOMER_NUMBER);

  public final ArrayList<DeskReport> results = new ArrayList<DeskReport>(DESK_NUMBER);
  
  public void perform(){
    ExecutorService executor = Executors.newFixedThreadPool(DESK_NUMBER);
    for (int i = 1; i <= DESK_NUMBER; i++) {
      executor.submit(new Desk(this, i));
    }

    executor.shutdown();
        try {
            executor.awaitTermination(20, TimeUnit.SECONDS);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
  }
  
  public void printResult(){
    int maxTimeS = 0;
    int maxItems = 0;
    int maxCustomers = 0;
    
    int minItems = Integer.MAX_VALUE;
    int minCustomers = Integer.MAX_VALUE;
    
    for(DeskReport r : results){
      if(r.getSpentTime() > maxTimeS){
        maxTimeS = r.getSpentTime();
      }
      
      if(r.getSoldItemCount() > maxItems){
        maxItems = r.getSoldItemCount();
      }
      if(r.getSoldItemCount() < minItems){
        minItems = r.getSoldItemCount();
      }
      
      
      if(r.getServedCustomerCount() > maxCustomers){
        maxCustomers = r.getServedCustomerCount();
      }
      if(r.getServedCustomerCount() < minCustomers){
        minCustomers = r.getServedCustomerCount();
      }
      
    }
    
    Date date = new Date(maxTimeS * 1000L);
    DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    String dateFormatted = formatter.format(date);
    
    
    System.out.println("---------------- RESULTS ----------------");
    System.out.println(DESK_NUMBER + " desks served " + CUSTOMER_NUMBER + " customers in " + dateFormatted);
    System.out.println("Troughput min ~ max:");
    System.out.println(minItems + "\t~\t" + maxItems + " \titems/desk");
    System.out.println(minCustomers + "\t~\t" + maxCustomers + "\tcustomers/desk");
  }
  
  public static void main(String[] args) {
    Simulation sim = new Simulation();
    sim.perform();
    sim.printResult();
  }
}
public class CustomerFactory {

  private Simulation simulation;
  private int capacity = 0;
  
  public CustomerFactory(Simulation simulation, int capacity){
    this.simulation = simulation;
    this.capacity = capacity;
  }

  public synchronized Customer getInstanceWithRandomCapacity(){
    if(capacity-- > 1){
      return new Customer(this.simulation.getRandomIntInRangeEnclosed(1,20));
    } else {
      return null;
    }
  }
  
}

public class Desk implements Runnable{
  private Simulation s = null;
  private int deskNo = 0;

  private int servedCustomerCount = 0;
  private int soldItemCount = 0;
  private int spentTime = 0;
  
  public Desk(Simulation s, int deskNo) {
    this.s = s;
    this.deskNo = deskNo;
  }
  
  public void run() {
    System.out.println("Desk " + deskNo + " opening...");

    Customer c = null;
    while ((c = s.customerFactory.getInstanceWithRandomCapacity()) != null) {
      servedCustomerCount++;
      for(int i=c.getItemCount(); i>1; i--){
        soldItemCount++;
        spentTime += s.getRandomIntInRangeEnclosed(s.ITEM_DURATION_S_MIN, s.ITEM_DURATION_S_MAX);
      }
      //get short break after each customer ;)
      sleep(Long.valueOf(s.getRandomIntInRangeEnclosed(s.ITEM_DURATION_S_MIN, s.ITEM_DURATION_S_MAX)));
    }
    
    s.results.add(new DeskReport(deskNo, servedCustomerCount, soldItemCount, spentTime));
    System.out.println("Desk " + deskNo + "\tclosing.\tcustomers " + servedCustomerCount + "\titems " + soldItemCount + "\ttime(s) " + spentTime);
  }
  
  private void sleep(long ms){
    try {
      Thread.sleep(ms);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

public class DeskReport {
  private int deskNo = 0;
  private int servedCustomerCount = 0;
  private int soldItemCount = 0;
  private int spentTime = 0;
  
  public DeskReport(int deskNo, int servedCustomerCount, int soldItemCount, int spentTime){
    this.deskNo = deskNo;
    this.servedCustomerCount = servedCustomerCount;
    this.soldItemCount = soldItemCount;
    this.spentTime = spentTime;
  }
  
  public int getDeskNo() {
    return deskNo;
  }

  public int getServedCustomerCount() {
    return servedCustomerCount;
  }

  public int getSoldItemCount() {
    return soldItemCount;
  }

  public int getSpentTime() {
    return spentTime;
  }
  
}

public class Customer{
  private int itemCount = 0;
  
  public Customer(int itemCount){
    this.itemCount = itemCount;
  }
  
  public int getItemCount(){
    return this.itemCount;
  }
}

The simulation is the most primitive, it demonstrates the work of the thread scheduler rather than the store. But if it is developed: to simulate the uneven "inflow" of customers to the store, the queue to the cash registers, the random choice of the cash register by the buyer, etc., you can learn a lot of interesting things about the work of stores. In the meantime, so as not to be completely meaningless, at least some primitive statistics are considered.

V
Vasilij Aleksashin, 2015-10-15
@TerraMorf

I would do this:
1. a collection of cash registers
2. a collection of customers and each has a collection of goods
3. processing time for one item = 3000ms
4. time between customer shifts = 5000ms
Launching a queue of customers at the cash registers.
While all the cash desks are busy - the rest of the customers are waiting
When the cash desk is vacated, a new customer goes to it
Time while the customer occupies the cash desk = number of goods * for the processing time of one product and plus the time for changing the buyer

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question