A
anggogo
Unregistered / Unconfirmed
GUEST, unregistred user!
现在我需要模拟一个急诊室的系统, 它包括从挂号, assessment, 到进入 treatment room 医治, 到最后判断是拿药离开,还是住院
我用了几个线程来完成这个东西, 但是现在有一个问题, 我的问题比较复杂, 我会努力说清楚, 还麻烦各位了.
读取病人的数据是从一个文本读取, 我假设第一个线程 T1 读取病人数据, 然后加入 Q1;
另外一个线程读取 Q1, 进行 assessment, 判断病情然后分配 priority, 并加入 Q2 ( 很明显,Q1只是一个 standard queue, 而Q2 就是一个 priority queue) 以下我用 waitQ 表示 Q2, 是 waiting patients 的意思.
前面这一段都还好做, 也执行正常. 到 treatment room 的时候就比较麻烦
treatment room 有三个, 其实也可以有 n 个, 暂时定为3个.
我做了一个数组, 包含3个线程, 分别执行三个 runnable 的 TreatmentRoom class, 最初的想法是, 我如何让这些 treatment rooms 开始和结束呢?
首先, 我必须等待 waitQ 有病人的时候开始工作, 但是我不能在 run() 里面有这样一句
while (waitQ.isEmpty());
这样一句有很大问题, 因为可以出现在一个 treatment room 开始工作之前, 其它 treatment room 已经看完所有病人, 结果这个线程就一直等待 (starvation)
第二, 我希望可以在 treatment room 线程之前可以交流, 以至我能了解到有多少间 treatment room 正在使用, 有多少又是空置的.
因此, 我做了一个 Message class ,用来模拟一个护士在这些 treatment rooms 之间通信. 代码如下
而在我的 treatmentRoom class 里, 构造器如下
waitQ 就是在等待的病人
departQ 就是直接拿药离开的病人
admitQ 就是需要住院的病人
log 是一个记录当前第几号病人进入房间看病, 花了多长时间, 有多少房间空闲之类信息的一个类, 不需要理会.
我的 run() 代码如下:
大致的代码就好像上面那样, 现在我的问题是, 我必须在 startTreatment 方法里用 Thread.Sleep() 一段时间, 才能正常完成所有的病人. 否则只能完成部分病人.
原因我也能想象的到, 如果是顺序的执行, 假设5个病人排队, 3个线程, 分别读取了一个病人后, 再读一个, 而其中一个线程发现 waitQ 已经空了, 于是就告诉 nurse, 可以下班了, 结果另外那两个也自动结束了. (我估计是这样的)
我给大家贴某一次的执行结果
我不明白为什么, room1 在看完第一个病人后就已经可以退出循环, 然后在 run() 的结尾打印"结束"
我也只是第一次用 JAVA 来做多线程的东西, 我觉得我可能是有一个地方的 synchronization 没有用好.
请各位指点.
万分感激!
我用了几个线程来完成这个东西, 但是现在有一个问题, 我的问题比较复杂, 我会努力说清楚, 还麻烦各位了.
读取病人的数据是从一个文本读取, 我假设第一个线程 T1 读取病人数据, 然后加入 Q1;
另外一个线程读取 Q1, 进行 assessment, 判断病情然后分配 priority, 并加入 Q2 ( 很明显,Q1只是一个 standard queue, 而Q2 就是一个 priority queue) 以下我用 waitQ 表示 Q2, 是 waiting patients 的意思.
前面这一段都还好做, 也执行正常. 到 treatment room 的时候就比较麻烦
treatment room 有三个, 其实也可以有 n 个, 暂时定为3个.
我做了一个数组, 包含3个线程, 分别执行三个 runnable 的 TreatmentRoom class, 最初的想法是, 我如何让这些 treatment rooms 开始和结束呢?
首先, 我必须等待 waitQ 有病人的时候开始工作, 但是我不能在 run() 里面有这样一句
while (waitQ.isEmpty());
这样一句有很大问题, 因为可以出现在一个 treatment room 开始工作之前, 其它 treatment room 已经看完所有病人, 结果这个线程就一直等待 (starvation)
第二, 我希望可以在 treatment room 线程之前可以交流, 以至我能了解到有多少间 treatment room 正在使用, 有多少又是空置的.
因此, 我做了一个 Message class ,用来模拟一个护士在这些 treatment rooms 之间通信. 代码如下
代码:
class Message
{
private int _msg;
private boolean roomsBusy[];
private int freeRoom;
public static int MORE_WAITING_PATIENT = 1;
public static int NO_MORE_WAITING_PATIENT = 2;
Message(int roomNum)
{
this(roomNum, MORE_WAITING_PATIENT);
}
Message(int roomNum, int msg)
{
_msg = msg;
roomsBusy = new boolean[roomNum];
freeRoom = roomNum;
}
public synchronized void send(int msg)
{
_msg = msg;
}
public synchronized int receive()
{
return _msg;
}
public synchronized void setBusy(int roomId)
{
roomsBusy[roomId - 1] = true;
freeRoom --;
}
public synchronized void setFree(int roomId)
{
roomsBusy[roomId - 1] = false;
freeRoom ++;
}
public synchronized int getFreeRoom()
{
return freeRoom;
}
public synchronized int getBusyRoom()
{
return roomsBusy.length - freeRoom;
}
}
代码:
treatmentRoom (int id,
Queue waitingList, Queue departList,
Queue admitList, LogTable log,
Message nurse)
{
roomId = id;
startTime = -1;
waitQ = waitingList;
departQ = departList;
admitQ = admitList;
this.log = log;
this.nurse = nurse;
}
departQ 就是直接拿药离开的病人
admitQ 就是需要住院的病人
log 是一个记录当前第几号病人进入房间看病, 花了多长时间, 有多少房间空闲之类信息的一个类, 不需要理会.
我的 run() 代码如下:
代码:
public void run()
{
Patient p;
while (nurse.receive()==Message.MORE_WAITING_PATIENT)
{
synchronized(waitQ)
{
p = (Patient)waitQ.leave();
}
// in case there is no waiting patient at this moment
if (p==null) continue;
nurse.setBusy(roomId);
startTreatment(p);
nurse.setFree(roomId);
synchronized(waitQ)
{
if (waitQ.isEmpty())
{
synchronized(nurse)
{
nurse.send(Message.NO_MORE_WAITING_PATIENT);
}
}
}
原因我也能想象的到, 如果是顺序的执行, 假设5个病人排队, 3个线程, 分别读取了一个病人后, 再读一个, 而其中一个线程发现 waitQ 已经空了, 于是就告诉 nurse, 可以下班了, 结果另外那两个也自动结束了. (我估计是这样的)
我给大家贴某一次的执行结果
在 Simulation is finished 后面的记录是通过 log 按照时间顺序打印出来的.Simulation is processing...
Time 45: 28064212 Priority 1 completes treatment in room 1
1 completes!
Time 25: 28064213 Priority 1 completes treatment in room 2
2 completes!
Time 22: 28064214 Priority 1 completes treatment in room 3
3 completes!
Simulation is finished
Time 13: 28064212 (emergency) arrives
Time 13: 28064213 (walk-in) arrives
Time 14: 28064214 (walk-in) arrives
Time 15: 28064215 (emergency) arrives
Time 15: 28064216 (walk-in) arrives
Time 17: 28064212 Priority 1 enters waiting room
Time 17: 28064213 Priority 1 enters waiting room
Time 18: 28064214 Priority 1 enters waiting room
Time 19: 28064215 Priority 1 enters waiting room
Time 19: 28064216 Priority 5 enters waiting room
Time 22: 28064214 Priority 1 completes treatment in room 3
Time 25: 28064213 Priority 1 completes treatment in room 2
Time 45: 28064212 Priority 1 completes treatment in room 1
我不明白为什么, room1 在看完第一个病人后就已经可以退出循环, 然后在 run() 的结尾打印"结束"
我也只是第一次用 JAVA 来做多线程的东西, 我觉得我可能是有一个地方的 synchronization 没有用好.
请各位指点.
万分感激!