本单元的总体任务是维护一个ABCDE共5楼座、10层的目标选择电梯系统。需要接受乘客的请求和增加电梯的请求,并运行相应电梯将乘客送达目的地。输出所有的电梯运行以及上下人行为。
一、同步块和锁
第五次作业中只有竖向电梯,每座各有一个,均可达1-10层,乘客请求出发地和目的地楼座一定相同。
1、第五次作业
由于只有五部电梯,并且所有请求对应的电梯是明确的,所以没有设置全局调度器,而是选择由输入线程与所有电梯共享一个候乘表对象,电梯直接从候乘表中取出自己对应的请求。为了简化其他类的设计,这里直接将候乘表设置为线程安全类,同步块具体代码如下:
public synchronized void addRequest(PersonRequest request) {
char fromBuilding = request.getFromBuilding();
this.requests.get(fromBuilding).add(request);
notifyAll();
}
public synchronized PersonRequest getMainRequest(char nowBuilding) {
while (requests.get(nowBuilding).isEmpty() && (!close)) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (requests.get(nowBuilding).isEmpty()) {
return null;
}
return requests.get(nowBuilding).get(0);
}
public synchronized ArrayList<PersonRequest> getForm(char nowBuilding) {
return requests.get(nowBuilding);
}
public synchronized PersonRequest getNowFloor(char nowBuilding, int nowFloor) {
ArrayList<PersonRequest> list = requests.get(nowBuilding);
for (PersonRequest personRequest : list) {
if (personRequest.getFromFloor() == nowFloor) {
list.remove(personRequest);
return personRequest;
}
}
return null;
}
public synchronized void close() {
close = true;
notifyAll();
}
public synchronized boolean checkOver(char nowBuilding) {
if (!close) {
return false;
} else {
return requests.get(nowBuilding).isEmpty();
}
}
public synchronized void output(String in) {
TimableOutput.println(in);
}
可以看出,添加请求、电梯空时获取请求getMainRequest,策略类获取当前楼座候乘表getForm,电梯上人getNowFloor,输入结束close,检查是否结束线程的checkOver和输出output都在同步块内。在某电梯线程或输入线程访问时均会阻塞其他线程的访问,以此保证线程安全。特别的,当电梯无人且主请求为空时,会执行wait()等待,输入线程每当进行输入之后会执行notifyAll()唤醒所有空置等待的电梯,以此可以避免电梯空时轮询占用CPU资源的问题。
PS:现在第二单元结束之后需再看这段代码其实有一些问题,也有可以优化的地方。
- 首先是getForm很有问题,它直接将该共享对象的一部分的指针(?)暴露给了同步块之外的部分,电梯的策略类使用的时候如果输入线程对其进行了修改,很容易出现RunTimeError,不过强测居然全都过了现在想想也是幸运。
- 之后是方法冗余的问题,checkOver函数完全可以综合进getMainRequest中,比如使用null作为返回值标记线程结束,而不需要单独写一个方法。
2、第六次作业
第六次作业在第五次作业的基础上增加了横向电梯,横向电梯可以到达相应层的所有座。乘客请求在第五次作业的基础上可以发出出发和目的地相同层不同座的请求,且请求保证在该层添加电梯1s后(保证了电梯一定先被完成添加)。由于出现了新增电梯的请求,在输入线程设置了了两个共享对象,一个乘客请求总队列ScheduleQueue负责存储所有输入的乘客请求,一个电梯增加请求队列ElevatorAddingQueue负责存储所有添加电梯的请求。同时每楼座的纵向电梯和每层的横向电梯共享一个候乘表,由调度器进行分配。与上一次思路相同,为了减轻线程类的思维量,这里直接将所有的共享对象设置为线程安全类。
ScheduleQueue同步块代码如下
public synchronized void addRequest(PersonRequest personRequest) {
waitingRequests.add(personRequest);
notifyAll();
}
public synchronized PersonRequest getRequest() {
while (waitingRequests.isEmpty()) {
if (end) {
return null;
}
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
return waitingRequests.remove(0);
}
public synchronized void setEnd() {
end = true;
notifyAll();
}
与第五次作业的逻辑十分相同,只是作为总表仅有添加请求、获取请求和设置结束三个情况(读取结束在获取请求方法里一并进行)。
ElevatorAddingQueue与上文代码几乎完全一致,不再赘述。
RequestQueue代码如下(没有再展示添加请求和设置结束方法):
public synchronized PersonRequest getRequestNowFloor(int nowFloor, int status) {
if (status >= 0) {
for (PersonRequest nowRequest : waitingRequests) {
if (nowRequest.getFromFloor() == nowFloor) {
if (nowRequest.getFromFloor() - nowRequest.getToFloor() < 0) {
waitingRequests.remove(nowRequest);
return nowRequest;
}
}
}
}
if (status <= 0) {
for (PersonRequest nowRequest : waitingRequests) {
if (nowRequest.getFromFloor() == nowFloor) {
if (nowRequest.getFromFloor() - nowRequest.getToFloor() > 0) {
waitingRequests.remove(nowRequest);
return nowRequest;
}
}
}
}
return null;
}
public synchronized PersonRequest getRequestNowBuilding(char nowBuilding) {
for (PersonRequest request : waitingRequests) {
if (request.getFromBuilding() == nowBuilding) {
waitingRequests.remove(request);
return request;
}
}
return null;
}
public synchronized boolean lookRequestNowBuilding(char nowBuilding) {
for (PersonRequest request : waitingRequests) {
if (request.getFromBuilding() == nowBuilding) {
//waitingRequests.remove(request);
return true;
}
}
return false;
}
public synchronized PersonRequest getRandomRequest() {
while (waitingRequests.isEmpty()) {
if (end) {
return null;
}
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
//System.out.println(waitingRequests.get(0));
return waitingRequests.get(0);
}
public synchronized boolean lookRequestNowFloor(int nowFloor, int status) {
//System.out.println(waitingRequests);
if (status >= 0) {
for (PersonRequest nowRequest : waitingRequests) {
if (nowRequest.getFromFloor() == nowFloor) {
if (nowRequest.getFromFloor() - nowRequest.getToFloor() < 0) {
return true;
}
}
}
}
if (status <= 0) {
for (PersonRequest nowRequest : waitingRequests) {
if (nowRequest.getFromFloor() == nowFloor) {
if (nowRequest.getFromFloor() - nowRequest.getToFloor() > 0) {
return true;
}
}
}
}
//System.out.println("false at look");
return false;
}
public synchronized int look(int status, int nowFloor, int id) { //-1表示结束,0表示原方向继续,1表示转向
//System.out.println("begin look"+id);
while (waitingRequests.isEmpty()) {
if (end) {
return -1;
}
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
for (PersonRequest personRequest : waitingRequests) {
//System.out.println(""+(personRequest.getFromFloor()-nowFloor>0)+status);
if ((personRequest.getFromFloor() - nowFloor > 0 && status == 1)
|| (personRequest.getFromFloor() - nowFloor < 0 && status == -1)) {
//System.out.println("panic at 0");
return 0;
}
}
//System.out.println("panic at 1");
return 1;
}
可以看出,电梯内部的策略方法被直接集成在了相应的请求队列中,同时所有逻辑加锁,防止某两个同座/楼层电梯同时获取请求的线程不安全导致一个人“分身”的情况。
1、https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BB%8F%E7%90%86%E5%BE%AE%E4%BF%A1%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E4%BC%9A%E5%91%98%E6%B3%A8%E5%86%8C%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E4%BC%9A%E5%91%98%E6%B3%A8%E5%86%8C%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E8%81%94%E7%B3%BB%E7%94%B5%E8%AF%9D%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E8%81%94%E7%B3%BB%E7%94%B5%E8%AF%9D%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BB%8F%E7%90%86%E5%BE%AE%E4%BF%A1%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E6%B3%A8%E5%86%8C%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%9C%A8%E7%BA%BF%E4%B8%8B%E8%BD%BD%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E6%B3%A8%E5%86%8C%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8APP%E4%B8%8B%E8%BD%BD%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%89%8B%E6%9C%BA%E5%AE%89%E8%A3%85%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%9C%A8%E7%BA%BF%E6%B3%A8%E5%86%8C%E7%BD%91%E5%9D%80%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%9C%A8%E7%BA%BF%E6%B3%A8%E5%86%8C%E7%BD%91%E5%9D%80%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%9C%A8%E7%BA%BF%E4%B8%8B%E8%BD%BD%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8APP%E4%B8%8B%E8%BD%BD%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%AD%A3%E8%A7%84%E7%BD%91%E6%8A%95%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%89%8B%E6%9C%BA%E7%89%88%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%89%8B%E6%9C%BA%E7%89%88%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%89%8B%E6%9C%BA%E5%AE%89%E8%A3%85%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%AD%A3%E8%A7%84%E7%BD%91%E6%8A%95%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E5%AE%89%E8%A3%85%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E4%B8%8B%E8%BD%BD%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%B9%B3%E5%8F%B0%E4%B8%8B%E8%BD%BD%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%B9%B3%E5%8F%B0%E4%B8%8B%E8%BD%BD%E5%BE%AE%E7%94%B519188306232%20
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E5%AE%89%E8%A3%85%E5%BE%AE%E4%BF%A119188306232
https://www.163.com/search?keyword=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E4%B8%8B%E8%BD%BD%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E6%B3%A8%E5%86%8C%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E7%99%BB%E5%BD%95%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E6%B3%A8%E5%86%8C%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E7%99%BB%E5%BD%95%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%80%8E%E4%B9%88%E4%B8%8B%E8%BD%BD%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%80%8E%E4%B9%88%E4%B8%8B%E8%BD%BD%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E4%B8%8B%E8%BD%BD%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E4%B8%8B%E8%BD%BD%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E6%B3%A8%E5%86%8C%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E6%B3%A8%E5%86%8C%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E7%99%BB%E5%BD%95%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%B9%B3%E5%8F%B0%E6%B3%A8%E5%86%8C%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E7%99%BB%E5%BD%95%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%B9%B3%E5%8F%B0%E6%B3%A8%E5%86%8C%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E6%B3%A8%E5%86%8C%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%9C%A8%E7%BA%BF%E5%92%A8%E8%AF%A2%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%9C%A8%E7%BA%BF%E5%92%A8%E8%AF%A2%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E5%B9%B3%E5%8F%B0%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E6%B3%A8%E5%86%8C%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BA%BF%E4%B8%8A%E5%B9%B3%E5%8F%B0%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E9%93%BE%E6%8E%A5%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%99%BB%E5%BD%95%E7%BD%91%E5%9D%80%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E9%93%BE%E6%8E%A5%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%99%BB%E5%BD%95%E7%BD%91%E5%9D%80%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E5%A4%9A%E5%B0%91%E5%BE%AE%E4%BF%A119188306232
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E7%BD%91%E5%9D%80%E5%A4%9A%E5%B0%91%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E5%AE%98%E7%BD%91%E7%99%BB%E5%BD%95%E5%BE%AE%E7%94%B519188306232%20
https://www.wapbaike.net/?s=%E6%96%B0%E7%99%BE%E8%83%9C%E5%85%AC%E5%8F%B8%E6%B8%B8%E6%88%8F%E6%B3%A8%E5%86%8C%E5%