Java多线程之银行出纳员仿真
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多线程之银行出纳员仿真的更多相关文章
- Thinking in Java---多线程仿真:银行出纳员仿真+饭店仿真+汽车装配工厂仿真
多线程一个非常有意思的作用就是用于仿真,这篇博客就会结合几个仿真实例来综合运用一下前面所学的多线程并发知识. 一.银行出纳员仿真 问题描写叙述:银行会有非常多来办业务的顾客,他们会排队等待服务:对于银 ...
- java多线程(精华版)
在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为 Java 编程语言提供了语言级的支持.本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观.读完本文以后,用户应 ...
- Java多线程编程——进阶篇二
一.线程的交互 a.线程交互的基础知识 线程交互知识点需要从java.lang.Object的类的三个方法来学习: void notify() 唤醒在此对象监视器上等待的单个 ...
- Java 多线程 锁 存款 取款
http://jameswxx.iteye.com/blog/806968 最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣.已经拟好了提纲,大概分为这几个主题: ja ...
- 【转】Java多线程学习
来源:http://www.cnblogs.com/samzeng/p/3546084.html Java多线程学习总结--线程概述及创建线程的方式(1) 在Java开发中,多线程是很常用的,用得好的 ...
- Java多线程详解
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)
对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...
- Java多线程之线程的同步
Java多线程之线程的同步 实际开发中我们也经常提到说线程安全问题,那么什么是线程安全问题呢? 线程不安全就是说在多线程编程中出现了错误情况,由于系统的线程调度具有一定的随机性,当使用多个线程来访问同 ...
- Java 多线程 死锁 隐性死锁 数据竞争 恶性数据竞争 错误解决深入分析 全方向举例
在几乎所有编程语言中,由于多线程引发的错误都有着难以再现的特点,程序的死锁或其它多线程错误可能只在某些特殊的情形下才出现,或在不同的VM上运行同一个程序时错误表现不同.因此,在编写多线程程序时,事先认 ...
随机推荐
- java 动态代码生成。
http://stackoverflow.com/questions/2320404/creating-classes-dynamically-with-java https://zeroturnar ...
- min—width的使用
在网页中,如果一个元素没有设置最小宽度(min-width),这时当浏览器缩小到一定程度时,元素中的布局可能会发生变化.如果想要保持布局不变,可以给该元素(如div)设置最小宽度属性 .box{ ba ...
- 方正S4101g笔记本电脑搜不到无线网络
方正S4101g这款笔记本的无线网卡有问题.不能识别高版本的WIFI信号.有时候链接上之后,就再也找不到无线网络信号了.有时候根本就找不到. 解决方法:把无线路由的发送模式和频率设置到最低.重启路 ...
- 在Windows上安装Maven
下载 Maven 最新版本. http://maven.apache.org/download.cgi 1,下载包后,解压到相应特定位置. 2,将 [解压位置]/bin 加入到Path 3, ...
- linux工具之log4j-LogBack-slf4j-commons-logging
log4j http://commons.apache.org/proper/commons-logging/ http://logging.apache.org/log4j/2.x/ The Com ...
- Linux下printf格式符%d、%lld、%llx、%u等【转自CSDN博客】
来源:http://blog.csdn.net/anycell/article/details/6966520 %d 有符号32位整数 %lld 有符号64位证书 %llx有符号64位16进制整数 % ...
- AngularJS_对象数组-filter-orderBy
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- com.opensymphony.module.sitemesh.filter.PageFilter 装饰页面
1.web.xml中配置: <filter> <filter-name>sitemeshFilter</filter-name> <filter-class& ...
- 编译工程时报illegal character:\65279--转
windows对UTF-8文件进行了特殊处理,对UTF-8的文本文件自动在前面加了三个byte(EF BB BF),javac编译时,读到最前面这三个byte时报错 illegal character ...
- mysql row number的实现
CREATE TABLE `test_id` (`id` int(11) NOT NULL DEFAULT 0 ,`name` varchar(255) CHARACTER SET utf8 COLL ...