package concurrent;

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 tm) {
serviceTime = tm;
} 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 rand = new Random(47); public CustomerGenerator(CustomerLine cq) {
customers = cq;
} public void run() {
try {
while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(300));
customers.put(new Customer(rand.nextInt(1000)));
// System.out.println(customers.toString());
}
} 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 customers;// 客户队列
private boolean servingCustomerLine = true;// 是否正在服务客户 public Teller(CustomerLine cq) {
customers = cq;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
Customer customer = customers.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;
} public synchronized int compareTo(Teller other) {
return customersServed < other.customersServed ? -1
: (customersServed == other.customersServed ? 0 : 1);
}
} class TellerManager implements Runnable {
private ExecutorService exec;
private CustomerLine customers;
private PriorityQueue<Teller> workingTellers = new PriorityQueue<Teller>();
private Queue<Teller> tellersDoingOtherThings = new LinkedList<Teller>();
private int adjustmentPeriod;
private static Random rand = new Random(47); public TellerManager(ExecutorService e, CustomerLine customers,
int adjustmentPeriod) {
exec = e;
this.customers = customers;
this.adjustmentPeriod = adjustmentPeriod;
Teller teller = new Teller(customers);
exec.execute(teller);
workingTellers.add(teller);
} /**
* 调整出纳员数量
* */
public void adjustTellerNumber() {
if (customers.size() / workingTellers.size() > 2) {
if (tellersDoingOtherThings.size() > 0) {
Teller teller = tellersDoingOtherThings.remove();
teller.serveCustomerLine();
workingTellers.offer(teller);
return;
}
Teller teller = new Teller(customers);
exec.execute(teller);
workingTellers.add(teller);
return;
}
if (workingTellers.size() > 1
&& customers.size() / workingTellers.size() < 2)
reassignOneTeller(); if (customers.size() == 0)
while (workingTellers.size() > 1)
reassignOneTeller();
} /**
* 分配一个出纳员
* */
private void reassignOneTeller() {
Teller teller = workingTellers.poll();
teller.doSomethingElse();
tellersDoingOtherThings.offer(teller);
} public void run() {
try {
while (!Thread.interrupted()) {
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");
} 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 Exception {
ExecutorService exec = Executors.newCachedThreadPool();
CustomerLine customers = new CustomerLine(MAX_LINE_SIZE);
exec.execute(new CustomerGenerator(customers));
exec.execute(new TellerManager(exec, customers, ADJUSTMENT_PERIOD));
if (args.length > 0)
TimeUnit.SECONDS.sleep(new Integer(args[0]));
else {
System.out.println("Press 'Enter' to quit");
System.in.read();
}
exec.shutdownNow();
}
}

Java多线程之银行出纳员仿真的更多相关文章

  1. Thinking in Java---多线程仿真:银行出纳员仿真+饭店仿真+汽车装配工厂仿真

    多线程一个非常有意思的作用就是用于仿真,这篇博客就会结合几个仿真实例来综合运用一下前面所学的多线程并发知识. 一.银行出纳员仿真 问题描写叙述:银行会有非常多来办业务的顾客,他们会排队等待服务:对于银 ...

  2. java多线程(精华版)

    在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为 Java 编程语言提供了语言级的支持.本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观.读完本文以后,用户应 ...

  3. Java多线程编程——进阶篇二

    一.线程的交互 a.线程交互的基础知识 线程交互知识点需要从java.lang.Object的类的三个方法来学习:    void notify()           唤醒在此对象监视器上等待的单个 ...

  4. Java 多线程 锁 存款 取款

    http://jameswxx.iteye.com/blog/806968 最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣.已经拟好了提纲,大概分为这几个主题: ja ...

  5. 【转】Java多线程学习

    来源:http://www.cnblogs.com/samzeng/p/3546084.html Java多线程学习总结--线程概述及创建线程的方式(1) 在Java开发中,多线程是很常用的,用得好的 ...

  6. Java多线程详解

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  7. java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)

    对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...

  8. Java多线程之线程的同步

    Java多线程之线程的同步 实际开发中我们也经常提到说线程安全问题,那么什么是线程安全问题呢? 线程不安全就是说在多线程编程中出现了错误情况,由于系统的线程调度具有一定的随机性,当使用多个线程来访问同 ...

  9. Java 多线程 死锁 隐性死锁 数据竞争 恶性数据竞争 错误解决深入分析 全方向举例

    在几乎所有编程语言中,由于多线程引发的错误都有着难以再现的特点,程序的死锁或其它多线程错误可能只在某些特殊的情形下才出现,或在不同的VM上运行同一个程序时错误表现不同.因此,在编写多线程程序时,事先认 ...

随机推荐

  1. C# 数组,ArrayList与List对象的区别

    在C#中,当我们想要存储一组对象的时候,就会想到用数组,ArrayList,List这三个对象了.那么这三者到底有什么样的区别呢? 我们先来了解一下数组,因为数组在C#中是最早出现的. 数组 数组有很 ...

  2. Python中的lambda函数

    今天在看书的时候,看到了这样的一条语句: if isinstance(value,int) or isinstance(value,float): split_function=lambda row: ...

  3. Axure轮播图

    制作步骤如下: 1.新建一个动态面板,并添加几个动态面板状态(tab) 2.在所建的几个动态面板状态中添加要显示的每个广告的图片和相对应的代表第几个广告的数字. 3.添加页面交互事件.添加事件是在页面 ...

  4. Daas

    联想到这些年遇到的各种客户使用桌面虚拟化的场景,深有感触.桌面虚拟化技术并不一定适合所有的用户和场景,也不仅仅只是技术方面的问题.加强安全的方法有千万种,为何此客户情守桌面虚拟化呢?某客户已经规模化实 ...

  5. 【转】Winform 去掉 最大化 最小化 关闭按钮(不是关闭按钮变灰)终极解决办法

    不墨迹, 如图 : 网上 看了,好多 给的 答案 乱码七糟,都是扯淡,于是乎 自己 写,代码如下:窗体的大小暂时设置为:(598, 362) 涂红的数据根据你的窗体大小改动 using System; ...

  6. js列表分页

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. ExtJs学习笔记之Button组件

    按钮Button组件 可以使用该组件的创建简单的按钮. 可以自定义属性包括 aligned icons, dropdown menus, tooltips 和 sizing options. 当出发点 ...

  8. ORACLE 常用数值函数

    1 ABS(n)返回数值弄参数的绝对值.它接受一个数值型值作为输入参数,或者任何可以隐式地转换为数值型值的值.并且返回数值型值的绝对值. Select abs(-1) from dual ABS(-1 ...

  9. C++中的空类与空结构体大小

    今天面试遇到了一个很有意思的问题,即空结构体在C++中所占的内存大小是多少?参见如下代码: #include <iostream> struct S0 { }; int main() { ...

  10. Angular学习(2)- ng-app

    此例子看alert弹出时的效果.当然,最重要的是ng-app="MyApp",这一个是怎么加载的. <!DOCTYPE html> <html ng-app=&q ...