您的位置:首页 > 职场人生

模拟银行某一时段的服务流程 ---- IBM面试题

2013-06-04 20:23 525 查看
注:本博客内容没有通过面试,呵呵...请不要盲信博客内容!!!

这段时间一直在找工作,说实话现在行情真不是太好,叫我去面试的大都是外包公司,而我又不很喜欢做外包,所以很郁闷,也挺焦急...这是背景。

今天下午又接到一外包公司的面试电话,是外包到IBM的,不知什么原因没有推掉,于是负责招聘的MM发来一道IBM的试题,说是做完让那边看完之后才能安排面试。于是乎,忙活了好大一会子,终于将其解决。

由于以前没做银行项目,对于并发这块也不是很熟悉,所以解决方式很别扭,也不知道是否对题目理解正确,现将解决方案发表于此,请大家指正。

试题信息

要求

请在一个小时内完成。

问题描述

请模拟银行某一时段的服务流程

银行有4个服务窗口,其中有三个是普通窗口,一个是VIP窗口。VIP窗口在没有VIP用户时也可以当作普通服务窗口办理业务。银行的服务流程描述如下:

首先到达的客户需要在门口领取一张号码纸,号码纸上写明了前面排队的人数和你的号码。
客户等待自己被服务。如果号码纸的的号码过期,即当前的号码大于号码纸的号码,则号码纸就过期了
如果VIP用户到达后,VIP用户进入VIP窗口办理,如果VIP窗口前面有其他的VIP用户,则排在其他VIP用户之后,如果有普通会员在办理,则服务完成后立刻服务VIP用户。
银行的业务员在服务完一个客户后,会根据号码纸依次通知下一个客户进行服务

用户的数据放在一个文本文件中

类似于如下所示(各列依次为:次序、客户类型、到达时间、服务时间):

1 普通 09:00 5
2 普通 09:00 6
3 普通 09:00 5
4 普通 09:02 9
5 普通 09:04 5
6 VIP 09:05 7
7 普通 09:10 5
8 普通 09:12 10
9 普通 09:15 5
10 VIP 09:18 5
11 普通 09:18 8
12 普通 09:19 5

输出

请输出每一个窗口的服务客户列表,以及每一个客户的等待时间

解决方案

首先定义客户类,客户类型以枚举表示,个人觉得题目不算复杂,因此并没有好好设计,没有将客户类抽象出父类,而是VIP客户和普通客户都由此类表示:

package com.ibm.bank;

import java.util.Date;

/**
* 客户类, 例子比较简单, 没有再提取父类, VIP和普通客户都用此类代表, 以customType区分.
* @author zyh
*/
public class Custom implements Comparable<Custom>{
private Long order;				// 客户次序
private CustomType customType;	// 客户类型
private Date arrivalDate;		// 到达时间
private int serviceTime;		// 服务时长

public long getOrder() {
return order;
}

public void setOrder(long order) {
this.order = order;
}

public CustomType getCustomType() {
return customType;
}

public void setCustomType(CustomType customType) {
this.customType = customType;
}

public Date getArrivalDate() {
return arrivalDate;
}

public void setArrivalDate(Date arrivalDate) {
this.arrivalDate = arrivalDate;
}

public int getServiceTime() {
return serviceTime;
}

public void setServiceTime(int serviceTime) {
this.serviceTime = serviceTime;
}

@Override
public int compareTo(Custom o) {
return this.order.compareTo(o.order);
}
}

/**
* 客户类型枚举类
* @author zyh
*/
enum CustomType {
VIP("the VIP custom."),
COMMON("the COMMON custom.");

private String description;

private CustomType(String desc) {
this.description = desc;
}

public String getDescription() {
return this.description;
}

@Override
public String toString() {
return this.description;
}
}


接着给出两个窗口类(VIP窗口和普通窗口),业务窗口类实现了Runnable接口,表示这是一个任务;在窗口中循环从客户端获取下一个客户(VIP窗口获取下一个VIP客户,如果接下来没有VIP客户了,则获取普通客户),如果客户存在则打印服务列表,然后休眠客户服务时长,如果接下来再没有客户了,则该窗口关闭(线程结束)。

VIP窗口:

package com.ibm.bank;

import java.util.concurrent.TimeUnit;

/**
* VIP窗口, 办理VIP用户业务, 如果没有VIP用户在等待, 也可以办理普通用户业务.
* @author zyh
*/
public class VIPWindow implements Runnable {
private Client client;

public VIPWindow(Client client) {
this.client = client;
}

@Override
public void run() {
Custom cs = null;
while ((cs = client.nextCustom(CustomType.VIP)) != null) {
long waitedTime = System.currentTimeMillis() - client.getServiceStartTime();
try {
System.out.println("VIP Window is Servicing for Custom " + cs.getOrder()
+ ", Custom Type: " + cs.getCustomType().name() + ", arrival time: "
+ String.format("%1$tF %1$tR", cs.getArrivalDate()) + ", waited time: "
+ waitedTime/1000 + "S");
// 服务时间
TimeUnit.MINUTES.sleep(cs.getServiceTime());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

普通窗口:

package com.ibm.bank;

import java.util.concurrent.TimeUnit;

/**
* 普通用户窗口
* @author zyh
*/
public class GeneralWindow implements Runnable {
private String windowName;
private Client client;

public GeneralWindow(Client client, String winName) {
this.client = client;
this.windowName = winName;
}

public void run() {
Custom cs = null;
while((cs = client.nextCustom(CustomType.COMMON)) != null) {
long waitedTime = System.currentTimeMillis() - client.getServiceStartTime();
try {
System.out.println("General Window(" + this.windowName + ") is Servicing for Custom "
+ cs.getOrder() + ", Custom Type: " + cs.getCustomType().name() + ", arrival time: "
+ String.format("%1$tF %1$tR", cs.getArrivalDate()) + ", waited time: "
+ waitedTime/1000 + "S");
TimeUnit.MINUTES.sleep(cs.getServiceTime());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public String getWindowName() {
return windowName;
}

public void setWindowName(String windowName) {
this.windowName = windowName;
}
}


最后是客户端代码,用一个LinkedList类存储解析得到的所有客户(可将其作为队列使用),然后在static代码块中解析客户信息文件并填充LinkedList,最后在main方法中创建了三个普通窗口线程和一个VIP窗口线程,丢进执行器ExecutorService 中:

package com.ibm.bank;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Client {
private static LinkedList<Custom> customList = new LinkedList<Custom>();
private Long serviceStartTime;

public Long getServiceStartTime() {
return serviceStartTime;
}

public Client() {
serviceStartTime = System.currentTimeMillis();
}

static {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/ibm/bank/customs.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
String line = reader.readLine();
String regex = "^\\d{1,2} [\\u4E00-\\u9FFF|\\w]{2,3} \\d{2}:\\d{2} \\d{1,}$";
Calendar calendar = Calendar.getInstance();
while(null != line && line.matches(regex)) {
String [] customInfo = line.split(" ");
Custom custom = new Custom();
custom.setOrder(Long.parseLong(customInfo[0]));
custom.setServiceTime(Integer.parseInt(customInfo[3]));
if (customInfo[1].equals("VIP")) {
custom.setCustomType(CustomType.VIP);
} else {
custom.setCustomType(CustomType.COMMON);
}
String [] time = customInfo[2].split(":");
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(time[1]));
custom.setArrivalDate(calendar.getTime());

customList.offer(custom);

line = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != reader) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
Client client = new Client();

ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new GeneralWindow(client, "第1普通窗口"));
executorService.execute(new GeneralWindow(client, "第2普通窗口"));
executorService.execute(new GeneralWindow(client, "第3普通窗口"));
executorService.execute(new VIPWindow(client));

executorService.shutdown();
}

/**
* 获取下一个客户
* @param customType 客户类型
* @return VIP窗口或者普通窗口要服务的下一个客户
*/
public synchronized Custom nextCustom(CustomType customType) {
if (customType == CustomType.VIP) {
Custom cs; int index = 0;
while (index < customList.size() && (cs = customList.get(index++)) != null) {
if (customType == cs.getCustomType()) {
customList.remove(cs);
return cs;
}
}
}
return customList.poll();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JAVA