仿真
- 通过使用并发,仿真的每个构件都可以成为其自身的任务,这使得仿真更容易编程。
银行出纳员仿真
- 可以表示任何属于以下的情况:对象随机地出现,并且要求由数量有限的服务器提供随机数量的服务时间。通过构建仿真可以确定理想的服务器数量。
package com21仿真;
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;
/**
* Created by Panda on 2018/5/30.
*/
class Customer{
private final int serviceTime;
public Customer(int serviceTime){this.serviceTime=serviceTime;}
public int getServiceTime(){return serviceTime;}
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 static Random random = new Random(47);
public CustomerGenerator(CustomerLine customers) {this.customers = customers;}
@Override
public void run() {
try{
while (!Thread.interrupted()){
TimeUnit.MILLISECONDS.sleep(random.nextInt(300));
customers.put(new Customer(random.nextInt(1000)));
}
}catch (InterruptedException e){
System.out.println("CustomerGenerator interrupted");
}
System.out.println("CustomerGenerator terminating");
}
}
class Teller implements Runnable,Comparable<Teller>{
private static int counter=0;
private final int id=counter++;
private int customersServed=0;
private CustomerLine customersLine;
private boolean servingCustomerLine=true;
public Teller(CustomerLine customers) {
this.customersLine = customers;
}
@Override
public synchronized int compareTo(Teller o) {
return customersServed< o.customersServed?-1:(customersServed==o.customersServed?0:1);
}
@Override
public void run() {
try{
while (!Thread.interrupted()){
Customer customer = customersLine.take();
TimeUnit.MILLISECONDS.sleep(customer.getServiceTime());
synchronized (this){
customersServed++;
while (!servingCustomerLine){
wait();
}
}
}
}catch (InterruptedException e){
System.out.println(this+" interrupted");
}
System.out.println(this+ "terminating");
}
public synchronized void doSomethingElse(){
customersServed=0;
servingCustomerLine=false;
}
public synchronized void serveCustomerLine(){
assert !servingCustomerLine:"already serving: "+this;
servingCustomerLine=true;
notifyAll();
}
public String toString(){return "Teller "+id+" ";}
public String shortString(){return "T"+id;}
}
class TellerManager implements Runnable{
private ExecutorService executorService;
private CustomerLine customersLine;
private PriorityQueue<Teller> workingTells=new PriorityQueue<>();
private Queue<Teller> tellersDoingOtherThing=new LinkedList<>();
private int adjustmentPeriod;
private static Random random = new Random(47);
public TellerManager(ExecutorService executorService ,CustomerLine customersLine,int adjustmentPeriod){
this.executorService=executorService;
this.customersLine=customersLine;
this.adjustmentPeriod=adjustmentPeriod;
Teller teller = new Teller(customersLine);
executorService.execute(teller);
workingTells.add(teller);
}
public void adjustTellerNumber(){
if(customersLine.size()/workingTells.size()>2){
if(tellersDoingOtherThing.size()>0){
Teller teller=tellersDoingOtherThing.remove();
teller.serveCustomerLine();
workingTells.offer(teller);
return;
}
Teller teller = new Teller(customersLine);
executorService.execute(teller);
workingTells.add(teller);
return;
}
if(workingTells.size()>1&&customersLine.size()/workingTells.size()<2){
reassignOneTeller();
}
if(customersLine.size()==0){
while (workingTells.size()>1) reassignOneTeller();
}
}
private void reassignOneTeller(){
Teller teller=workingTells.poll();
teller.doSomethingElse();
tellersDoingOtherThing.offer(teller);
}
@Override
public void run() {
try{
while (!Thread.interrupted()){
TimeUnit.MILLISECONDS.sleep(adjustmentPeriod);
adjustTellerNumber();
System.out.print(customersLine+"{ ");
for(Teller teller:workingTells){
System.out.print(teller.shortString()+" ");
}
System.out.println("}");
}
}catch (InterruptedException e){
System.out.println(this+"interrupted");
}
System.out.println(this+"terminating");
}
public String toString(){return "TellerManger ";}
}
public class BankTellerSimulation {
static final int MAX_LINE_SIZE=50;
static final int ADJUSTMENT_PERIOD=1000;
public static void main(String[] args) throws Exception{
ExecutorService executorService = Executors.newCachedThreadPool();
CustomerLine customersLine =new CustomerLine(MAX_LINE_SIZE);
executorService.execute(new CustomerGenerator(customersLine));
executorService.execute(new TellerManager(executorService,customersLine,ADJUSTMENT_PERIOD));
if(args.length>0) TimeUnit.SECONDS.sleep(new Integer(args[0]));
else {
System.out.printf("Press Enter to quit") ;
System.in.read();
}
executorService.shutdownNow();
}
/**
*
* customersLine.size()3
workingTells.size()1
[200][207]{ T1 T0 }
customersLine.size()4
workingTells.size()2
[861][258][140][322]{ T1 T0 }
customersLine.size()6
workingTells.size()2
[575][342][804][826][896][984]{ T2 T0 T1 }
customersLine.size()10
workingTells.size()3
[984][810][141][12][689][992][976][368][395][354]{ T3 T2 T1 T0 }
customersLine.size()8
workingTells.size()4
[395][354][222][687][634][317][242][698]{ T3 T2 T1 T0 }
customersLine.size()8
workingTells.size()4
[698][899][665][909][209][158][273][894]{ T3 T2 T1 T0 }
customersLine.size()7
workingTells.size()4
[984][533][8][328][779][882][37]{ T2 T0 T1 }
*/
}