线程试题

线程试题

   

 模拟实现银行业务调度系统逻辑,具体需求如下:

    银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。

    有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。

    异步随机生成各种类型的客户,生成各类型用户的概率比例为:VIP客户 :普通客户 :快速客户 = 163

    客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

    各类型客户在其对应窗口按顺序依次办理业务。

    当VIP6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

    随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。

    不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。


   分析

  在这了程序中有3种窗口并对外提供他们他们独立的号码,在现实中3个取号口在一个地方,所以设计一个单例模式的号码机并对外提供3种客户号码的获取方法.

   用户号码是独立的,他对外提供创新新号码和取出已产生的号码,因为号码数据有这个类产生,这个类拥有号码这个数据,就要对外提供取号码的方法

  柜台类:柜台是一个类,他中有一个属性表明他是什么柜台,并进行相应的取号操作

  人来时会创建新的号码并存在号码生产器内功柜台适用

  

  编写代码

    NumberManager :用于管理数字

    定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。

    定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。

    NumberManager类提供了数字的管理,并且存储这些数字,并要对外提供存和取得方法

package com.itheima.bank;

import java.util.ArrayList;
import java.util.List;

//数字管理类

public class NumberManager {
	int number = 1;
	List<Integer> list = new ArrayList<Integer>();
	
	//添加数字
	public synchronized int genereteNewNumber(){
		list.add(number);
		return number++;
	}
	
	//拿出数字并删除
	public synchronized Integer fetchNumber(){
		Integer num = null;
		if(list.size()>0){
			num = list.remove(0);
		}
		return num;
	}	
}


   NumberMachine:

   单例模式,对外提供方对象.创建3NumberManager对象并且对外提供访问方法

   定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。

   将NumberMachine类设计成单例。

package com.itheima.bank;

public class NumberMachine {
	private NumberManager common = new NumberManager();
	private NumberManager express = new NumberManager();
	private NumberManager vip = new NumberManager();
	
	
    //对外提供3种窗口的数字管理器
	public NumberManager getCommonManager(){
		return common;
	}
	public NumberManager getExpressManager(){
		return express;
	}
	public NumberManager getVipManager(){
		return vip;
	}
	
	private static NumberMachine numberMachine = new NumberMachine();
	private NumberMachine(){}
	
	//对外提供自己的对象
	public static NumberMachine getInstance(){
		return numberMachine;
	}
	
	
}

CustomerType枚举类存储3种客户

   系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。

   重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。

package com.itheima.bank;

public enum CustomerType {
	COMMON,EXPRESS,VIP;
	
	@Override
	public String toString() {
		switch(this){
		case COMMON :
			return "普通";
		case EXPRESS :
			return "快速";
		case VIP :
			return name();
		}
		return null;
	}
}

ServiceWindow类 用线程根据客户类型找到相应数字的Numbermanager并拿到集合内的数字

   定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。

   定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。

package com.itheima.bank;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ServiceWindow {
	

	CustomerType type = CustomerType.COMMON;
	private int windowId = 1;
	public void setType(CustomerType type) {
		this.type = type;
	}
	public void setWindowId(int windowId) {
		this.windowId = windowId;
	}
	
	public void start(){
		//我原先用的定时器来检查对象,后来比对老师的代码发现while能很大提高效率
		Executors.newSingleThreadScheduledExecutor().execute(
				new Runnable(){
					//判断该类为什么窗口并对应该窗口的操作
					public void run() {
						while(true){
							
							switch(type){
							case COMMON:
								commonService();
								break;
							case EXPRESS:
								expressService();
								break;
							case VIP:
								vipService();
							}
						}
					}
					
				});
	}

	
	
	//vip窗口操作
	private void vipService() {
		Integer num = NumberMachine.getInstance().getVipManager().fetchNumber();
		System.out.println("第" + windowId + "号" + type + "准备接收" + type + "客户");
		
		if(num != null){
			System.out.println("第" + windowId + "号" + type + "窗口正在为" + num + "号" + type + "客户服务" );
			int time = new Random().nextInt(Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME) + Constants.MIN_SERVICE_TIME;
			try {
				Thread.sleep(time * 1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("第" + windowId + "号" + type + "窗口为" + num + "号" + type + "客户服务结束,用时" + time + "秒");
		} else {
			System.out.println("第" + windowId + "号" + type + "未接收到" + type + "客户");
			this.commonService();
		}
		
	}

	//快速窗口操作
	private void expressService() {
		Integer num = NumberMachine.getInstance().getExpressManager().fetchNumber();
		System.out.println("第" + windowId + "号" + type + "准备接收" + type + "客户");
		
		if(num != null){
			System.out.println("第" + windowId + "号" + type + "窗口正在为" + num + "号" +type + "客户服务" );
			try {
				Thread.sleep(Constants.MIN_SERVICE_TIME);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("第" + windowId + "号" + type + "窗口为" + num + "号" + type + "客户服务结束,用时" +Constants.MIN_SERVICE_TIME + "秒");
		}  else{
			System.out.println("第" + windowId + "号" + type + "未接收到" + type + "客户");
			this.commonService();
		}
	}

	//普通窗口的操作
	private void commonService() {
		Integer num = NumberMachine.getInstance().getCommonManager().fetchNumber();
		System.out.println("第" + windowId + "号" + type + "准备接收普通客户");
		if(num != null){
			System.out.println("第" + windowId + "号" + type + "窗口正在为" + num + "号" + "普通客户服务" );
			int time = new Random().nextInt(Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME) + Constants.MIN_SERVICE_TIME;
			try {
				Thread.sleep(time * 1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("第" + windowId + "号" + type + "窗口为" + num + "号" + "普通客户服务结束,用时" + time + "秒");
		} else {
			System.out.println("第" + windowId + "号" + type + "窗口未接到普通客户,休息一秒钟");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			}
	}
	
	
}

MainClass类 用线程按比例创建3种客户,创建36serviceWindow

   用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。

   接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。

package com.itheima.bank;

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MainClass {

	public static void main(String[] args) {
		for(int i=1; i<5; i++){
			ServiceWindow common = new ServiceWindow();
			common.setWindowId(i);
			common.start();
		}
		ServiceWindow vip = new ServiceWindow();
		vip.setType(CustomerType.VIP);
		vip.start();
		ServiceWindow express = new ServiceWindow();
		express.setType(CustomerType.EXPRESS);
		express.start();
		
		//用定时器按比例产生3种客户
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						int num = NumberMachine.getInstance().getCommonManager().genereteNewNumber();
						System.out.println(num + "普通客户产生");
					}
				}, 
				0, 
				Constants.COMMON_CUSTOMER_INTERVAL_TIME, 
				TimeUnit.SECONDS
				);
		
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						int num = NumberMachine.getInstance().getExpressManager().genereteNewNumber();
						System.out.println(num + "快速客户产生");
					}
				}, 
				0, 
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 3, 
				TimeUnit.SECONDS
				);
		
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						int num = NumberMachine.getInstance().getVipManager().genereteNewNumber();
						System.out.println(num + "vip客户产生");
					}
				}, 
				0, 
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, 
				TimeUnit.SECONDS
				);
	}

}


Constants

   定义三个常量:MAX_SERVICE_TIMEMIN_SERVICE_TIMECOMMON_CUSTOMER_INTERVAL_TIME

package com.itheima.bank;

public class Constants {
	public static final int COMMON_CUSTOMER_INTERVAL_TIME = 1;
	public static final int MAX_SERVICE_TIME = 10;
	public static final int MIN_SERVICE_TIME = 1;
}

 运行结果

第3号普通准备接收普通客户
第2号普通准备接收普通客户
第1号快速准备接收快速客户
第1号VIP准备接收VIP客户
第3号普通窗口未接到普通客户,休息一秒钟
第1号普通准备接收普通客户
第1号普通窗口未接到普通客户,休息一秒钟
第1号VIP未接收到VIP客户
第4号普通准备接收普通客户
第4号普通窗口未接到普通客户,休息一秒钟
第1号快速未接收到快速客户
第1号快速准备接收普通客户
第2号普通窗口未接到普通客户,休息一秒钟
第1号快速窗口未接到普通客户,休息一秒钟
第1号VIP准备接收普通客户
第1号VIP窗口未接到普通客户,休息一秒钟
1普通客户产生
1快速客户产生
1vip客户产生
2普通客户产生
第1号VIP准备接收VIP客户
第3号普通准备接收普通客户
第1号普通准备接收普通客户
第2号普通准备接收普通客户
第4号普通准备接收普通客户
第1号快速准备接收快速客户
第4号普通窗口正在为1号普通客户服务
第2号普通窗口正在为2号普通客户服务
第1号普通窗口未接到普通客户,休息一秒钟
第3号普通窗口未接到普通客户,休息一秒钟
第1号VIP窗口正在为1号VIP客户服务
第1号快速窗口正在为1号快速客户服务
第1号快速窗口为1号快速客户服务结束,用时1秒
第1号快速准备接收快速客户
第1号快速未接收到快速客户
第1号快速准备接收普通客户
第1号快速窗口未接到普通客户,休息一秒钟
3普通客户产生
第3号普通准备接收普通客户
第1号普通准备接收普通客户
第3号普通窗口未接到普通客户,休息一秒钟
第1号普通窗口正在为3号普通客户服务
第1号快速准备接收快速客户
第1号快速未接收到快速客户
第1号快速准备接收普通客户
第1号快速窗口未接到普通客户,休息一秒钟
4普通客户产生
第4号普通窗口为1号普通客户服务结束,用时2秒
第4号普通准备接收普通客户
第4号普通窗口正在为4号普通客户服务
第3号普通准备接收普通客户
第3号普通窗口未接到普通客户,休息一秒钟
2快速客户产生
第1号快速准备接收快速客户
第1号快速窗口正在为2号快速客户服务
第1号快速窗口为2号快速客户服务结束,用时1秒
第1号快速准备接收快速客户
第1号快速未接收到快速客户
第1号快速准备接收普通客户
第1号快速窗口未接到普通客户,休息一秒钟
5普通客户产生
第3号普通准备接收普通客户
第3号普通窗口正在为5号普通客户服务
第1号快速准备接收快速客户
第1号快速未接收到快速客户
第1号快速准备接收普通客户
第1号快速窗口未接到普通客户,休息一秒钟
6普通客户产生
第1号VIP窗口为1号VIP客户服务结束,用时4秒
第4号普通窗口为4号普通客户服务结束,用时2秒
第1号VIP准备接收VIP客户
第4号普通准备接收普通客户
第1号VIP未接收到VIP客户
第4号普通窗口正在为6号普通客户服务
第1号VIP准备接收普通客户
第1号VIP窗口未接到普通客户,休息一秒钟
第1号快速准备接收快速客户
第1号快速未接收到快速客户
第1号快速准备接收普通客户
第1号快速窗口未接到普通客户,休息一秒钟





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值