【问题标题】:Concurrent Programming in Java. Trying to simulate a set of checkout countersJava中的并发编程。试图模拟一组收银台
【发布时间】:2018-10-19 10:44:59
【问题描述】:

我正在尝试使用 Java 模拟购物中心中的一组结帐柜台。

这是假设。有5个结账柜台。就像真正的购物中心一样,每个柜台都有一条线。每个柜台一次服务一位顾客。

我尝试如下实现:

  1. 每个客户都是一个运行类似于生产者-消费者问题中的生产者线程的类。客户是阻塞队列的一部分。我将不知何故需要一组阻塞队列来模拟 5 个结帐柜台前的 5 行。我如何做到这一点。

  2. 结帐计数器已定义为单线程执行器服务。所以现在将有 5 个执行程序一次服务一个(生产者)线程。我已经定义了一个执行器数组列表来模拟这组 5 个。

  3. 在计数器上,执行器服务一次从其对应队列中执行一个线程(即消费者正在消费生产者产生的东西)。

我的逻辑对吗?

我有一些代码,但我不确定这段代码是否正确执行了我的逻辑。

请帮忙。 干杯..

代码:

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();
                }
            }
        }
    }

}

客户.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();
        }
    }
}

驱动程序.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");
    }

}

【问题讨论】:

  • 我们是在谈论结账柜台,每个柜台都有自己的行吗?或者我们是在谈论一个结账柜台,那里有很长的队伍在等待,一旦结账柜台可用,人们就会被叫到前面?
  • 每个柜台都有自己的路线。
  • 欢迎来到 SO。所以每个结账都有自己的BlockingQueue&lt;Runnable&gt;。听起来不错。您需要一个类来将客户随机添加到这些队列中,我想为每个客户设置随机不同的处理时间。
  • 嗨@c0der .. 谢谢。我更新了代码。你能检查一下,让我知道到目前为止我对一个结帐柜台的逻辑是否正确吗?你能告诉我我的要求是否只是意味着我必须在一个循环中为 n 个结帐柜台执行相同的逻辑?谢谢:)
  • 这里的问题通常与解决问题有关。请测试您的代码并在您对特定问题有疑问时发布minimal reproducible example

标签: java multithreading parallel-processing executorservice producer-consumer


【解决方案1】:

您的模拟可能需要考虑更多功能。例如,您可能需要考虑以下部分或全部设计注意事项:

客户

每个客户都有以下特点

  • 要购买的一组物品。
    • 所有商品都在一次交易中购买,而不是一次购买一个
    • 单个事务中可能有 0..* 个项目。
    • 0 项交易会产生 0.00 美元的收据。
  • 客户识别
  • 到达收银台的时间
  • 完成结帐交易的时间
  • 购买交易的价值(即收据)

结帐柜台

每个收银台都有以下特点

  • 等待结账的顾客排队。

  • 队列中可能有 0..* 个客户在等待结账

  • 队列中的客户数量可供每位客户使用 入队前

  • 客户总是选择最短的可用结账队列

  • 一旦进入结账队列,所有客户都会留在该队列中,直到他们 交易服务。

  • 结帐柜台 ID

  • 自开店以来服务的顾客总数

    • 0 项交易不会增加所服务客户的总数
  • 结账柜台处理的所有销售总额

商店库存

可供购买的商品集合是商店库存。 每个项目都有以下特点

  • 项目 ID

  • 物品成本

客户购买的商品集仅包含每个商品的商品 ID。特定的商品 ID 可能会在客户选择购买的商品列表中出现多次。

【讨论】:

    【解决方案2】:

    我的逻辑如下:

    1. 将结帐计数器编写为自己的线程
    2. 将该行(客户行)写为普通列表。它不必是BlockingDeque,因为每个结帐柜台都有自己的线路。

    这样它就可以像真正的超市一样运作,每个收银台都有自己的线路。

    基于此我觉得写代码应该更符合逻辑。

    【讨论】:

    • 嗨,马克..谢谢。我更新了代码。你能检查一下,让我知道到目前为止我对一个结账柜台的逻辑是否正确吗?你能告诉我我的要求是否只是意味着我必须在一个循环中为 n 个结帐柜台执行相同的逻辑?谢谢:)
    • 代码看起来不错,不过我自己没有运行过。是的,我只需创建一个包含 n 个结帐计数器的数组并为每个计数器启动线程。这样每个柜台都在做自己的事情,而其他人在做自己的事情!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多