收银员与顾客问题其实就是一个典型的生产者和消费者的问题。
在这个问题里面,收银员和顾客哪个是生产者哪个是消费者,这个很重要,所以就有了以下的模块:
顾客是生产者角色,收银员是消费者模块
其中我们还需要一个中间人来传递生产者与消费者的数据发现和消费
那么就有了以下代码:
cashier类(中间类作用是数据发现与消费)
public class cashier {
private int customer;
private boolean state = false;
public synchronized void put(int i) {
//如果有顾客,等待消费
if (state) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有顾客,生产顾客
this.customer = i;
System.out.println("第" + this.customer + "个顾客来到收银员柜台前");
// 修改顾客状态
state = true;
//唤醒其他等待的线程
notifyAll();
}
public synchronized void get(String name) {
//如果没有顾客,则等待
if (!state) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有顾客
System.out.println("第" + this.customer + "个顾客,结账完毕"+" by "+name);
//修改状态
state = false;
//唤醒其他等待的线程
notifyAll();
}
}
Customer类(担任的角色是消费者,也就是我们收银员)
public class Customer implements Runnable {
cashier b = new cashier();
String name = null;
public Customer(cashier b, String name) {
this.b = b;
this.name = name;
}
@Override
public void run() {
while (true) {
b.get(name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Producer类**(担任的角色是生产者,也就是我们顾客)
public class Producer implements Runnable {
private cashier b;
private int count = 0;
public Producer(cashier b,int count) {
this.b = b;
this.count = count;
}
@Override
public void run() {
for (int i = 1; i <= count; i++) {
b.put(i);
}
}
}
剩下的就是使用一个main方法去调用它的模块了。
Main类
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入有几个顾客:");
cashier b = new cashier();
int providerCount = scanner.nextInt();
Producer p = new Producer(b, providerCount);
ArrayList<Customer> customers = new ArrayList<>();
System.out.print("请输入有几个收银员:");
int customerCount = scanner.nextInt();
for (int i = 0; i < customerCount; i++) {
customers.add(new Customer(b, "收银员"+i));
}
Thread th1 = new Thread(p);
ArrayList<Thread> threads = new ArrayList<>();
for (Customer customer : customers) {
threads.add(new Thread(customer));
}
th1.start();
for (Thread thread : threads) {
thread.start();
}
}
}