银行出纳员仿真
2020-03-21 本文已影响0人
桐桑入梦
package concurrency;
import java.io.IOException;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Customer{
private final int serviceTime;
public Customer(int serviceTime){
this.serviceTime = serviceTime;
}
public int getServiceTime(){
return serviceTime;
}
@Override
public String toString(){
return "[" + serviceTime + "]";
}
}
class CustomerLine extends ArrayBlockingQueue<Customer>{
public CustomerLine(int maxLineSize){
//初始化调用父类的构造函数
super(maxLineSize);
}
public String toString(){
if(this.size() == 0)
return "[Empty]";
StringBuilder result = new StringBuilder();
for(Customer customer : this)
result.append(customer);
return result.toString();
}
}
class CustomerGenerator implements Runnable{
//阻塞队列,用于添加用户
private CustomerLine customers;
private Random rand = new Random(47);
public CustomerGenerator(CustomerLine customers){
this.customers = customers;
}
@Override
public void run(){
try{
while(!Thread.interrupted()){
//在随机睡眠一段之间之后向阻塞队列中添加一个顾客元素
TimeUnit.MILLISECONDS.sleep(rand.nextInt(300));
customers.put(new Customer(rand.nextInt(1000)));
}
}catch(InterruptedException e){
System.out.println("CustomerGenerator interuped");
}
System.out.println("CustomerGenerator terminating");
}
}
class Teller implements Runnable, Comparable<Teller>{
private static int counter = 0;
private final int id = counter++;
private CustomerLine customers;
private int customerServied = 0;
private boolean servingCustomerLine = true;
public Teller(CustomerLine customers){
this.customers = customers;
}
@Override
public void run(){
try{
while(!Thread.interrupted()){
//从阻塞队列取出一个顾客元素,为她服务一段时间
Customer customer = customers.take();
TimeUnit.MILLISECONDS.sleep(customer.getServiceTime());
//更新出纳员已经服务的顾客人数,需要加锁访问
synchronized(this){
customerServied++;
//判断是否需要继续工作,如果不需要,那么阻塞等待
while(!servingCustomerLine)
wait();
}
}
}catch(InterruptedException e){
System.out.println(this + "interrupted");
}
System.out.println(this + "terminating");
}
//如果顾客不是很多,调用此方法,让出纳员休息或者做其他的事情
public synchronized void doSomethingElse(){
customerServied = 0;
servingCustomerLine = false;
}
//让出纳员处理顾客
public synchronized void serveCustomerLine(){
//如果这个出纳员正在休息,那么打印already...
assert !servingCustomerLine : "already serving: " + this;
servingCustomerLine = true;
//唤醒休息的出纳员,不是唤醒所有的出纳员,只是当前的这个
notifyAll();
}
@Override
public String toString(){
return "Teller " + id + " ";
}
public String shortString(){
return "T" + id;
}
@Override
public synchronized int compareTo(Teller that){
//比较之后的顺序是 -1 , 0 , 1
return customerServied < that.customerServied ? -1 : ( customerServied == that.customerServied ? 0 : 1);
}
}
class TellerManager implements Runnable{
private ExecutorService exec;
//顾客对应的阻塞队列,方便招聘出纳员时候引用队列
private CustomerLine customers;
//按照工作量小的出纳员优先接待顾客,这里是正在做出纳工作的Tellers
private PriorityQueue<Teller> workingTellers = new PriorityQueue<>();
//做其他事情的出纳员
private Queue<Teller> tellersDoingOtherThings = new LinkedList<>();
private int adjustmentPeriod;
private static Random rand = new Random(47);
public TellerManager(ExecutorService exec, CustomerLine customers, int adjustmentPeriod){
this.exec = exec;
this.customers = customers;
this.adjustmentPeriod = adjustmentPeriod;
Teller teller = new Teller(customers);
workingTellers.add(teller);
exec.execute(teller);
}
public void adjustTellerNumber(){
//如果顾客的数量很多,那么添加Teller数量
if(customers.size() / workingTellers.size() > 2){
//如果有空闲的Teller,那么添加到工作队列
if(tellersDoingOtherThings.size() > 0){
//从其他的事情(阻塞中)中出来,进入工作的优先队列中
Teller teller = tellersDoingOtherThings.remove();
//唤醒阻塞的该任务
teller.serveCustomerLine();
//优先队列的offer方法和add方法类似
workingTellers.offer(teller);
return ;
}
Teller teller = new Teller(customers);
exec.execute(teller);
workingTellers.add(teller);
return ;
}
//如果工作人员不止一个,而且等待的顾客不是很多,那么这里只用一个Teller
if(workingTellers.size() > 1 && customers.size() / workingTellers.size() < 2){
//让Teller休息(阻塞)
reassingOneTeller();
}
if(customers.size() == 0)
while(workingTellers.size() > 1)
reassingOneTeller();
}
private void reassingOneTeller(){
Teller teller = workingTellers.poll();
teller.doSomethingElse();
tellersDoingOtherThings.offer(teller);
}
@Override
public void run() {
try{
while(!Thread.interrupted()){
//每隔一段时间,调整Teller的数量
TimeUnit.MILLISECONDS.sleep(adjustmentPeriod);
adjustTellerNumber();
System.out.print(customers + " {");
for(Teller teller : workingTellers)
System.out.print(teller.shortString() + " ");
System.out.println("}");
}
}catch(InterruptedException e){
System.out.println(this + "interrupted");
}
System.out.println(this + "terminating");
}
@Override
public String toString(){
return "TellerManager ";
}
}
//银行出纳员仿真
public class BankTellerSimulation {
static final int MAX_LINE_SIZE = 50;
static final int ADJUSTMENT_PERIOD = 1000;
public static void main(String[] args) throws InterruptedException, IOException {
ExecutorService exec = Executors.newCachedThreadPool();
CustomerLine customers = new CustomerLine(MAX_LINE_SIZE);
//Customer生成器用于生成客户的阻塞队列,请求出纳员的服务
exec.execute(new CustomerGenerator(customers));
//传入exec是为了方便提交新的Teller任务
exec.execute(new TellerManager(exec, customers, ADJUSTMENT_PERIOD));
//运行指定的之间之后退出
if(args.length > 0)
TimeUnit.SECONDS.sleep(Integer.parseInt(args[0]));
else{
System.out.println("Press 'Enter' to quit");
System.in.read();
}
exec.shutdownNow();
}
}