OO 博客 第二单元

第五次作业总结

本次作业的基本目标是模拟多线程实时电梯系统,熟悉线程的创建、运行等基本操作,熟悉多线程的设计方法。

共享对象

Checkend类的checkend,PersonRequests类的personRequestsA……personRequestsE和waitingpersonRequestsA……waitingpersonRequestsE

同步块的设置或锁的选择

在这次作业中我没有用到同步块,在线程锁的设置方面上我在我把sychronized关键字设在了Checkend和PersonRequests类中的所有方法上

为了防止轮询我并没有使用wait()和 notify()方法,而是通过sleep()线程防止轮询CPU过多占用

|- Main:主类
|- Checkend:读入线程与调度器交互的共享对象
|- Dispatcher:调度器线程
|- PersonRequests:电梯内外的队列。作为电梯外的队列,是调度器与电梯交互的共享对象。
|- Elevator:电梯线程
|- SecureTimableOutput:线程安全输出

 

 

bug

在强测中出现了4个REAL_TIME_LIMIT_EXCEED,在我的代码中RTLE并不是因为线程锁死,而是因为算法并不是最优,在第六次作业中我采用了LOOK算法便可以解决RTLE问题

第六次作业总结

模拟一个多线程实时电梯系统,初始每个楼座有对应的一台电梯,可以在楼座内 1-10层之间运行;新增楼座与楼座之间移动的环形电梯,可以在五个楼座之间运行;可动态增加横向、纵向电梯;乘客的请求只能是同楼座或同楼层。

共享对象

Checkend类的checkend,PersonRequests类的allLongDisPersonRequests、allCirdisPersonRequests,为了最优分配环向电梯和纵向电梯还需要共享电梯数量所以有ArrayList<LongitudinalDispatcher> allLongDisarray和ArrayList<CircumferentialDispatcher> allCirDisarray

同步块的设置或锁的选择

本次作业中我没有使用同步块方法,使用的是ReentrantReadWriteLock读写锁,放弃使用了sychronized关键字,唯一使用sychronized的类是线程安全输出类SecuredTimableOutput

为了防止轮询我并没有使用wait()和 notify()方法,而是通过sleep()线程防止轮询CPU过多占用

|- Main:主类
|- Checkend:读入线程与调度器交互的共享对象
|- CircumferentialDispatcher:环向电梯调度器线程
|- LongitudinalDispatcher:纵向电梯调度器线程
|- PersonRequests:电梯内外的队列。作为电梯外的队列,是调度器与电梯交互的共享对象。
|- Elevator:电梯线程
|- SecureTimableOutput:线程安全输出

 

 

bug

在本次作业中强测全部ac,互测中没有测中人也没有被人hack,作业中使用了LOOK算法以及多台电梯合理分配人数,所以这次作业中没有出现RTLE的错误,使用了线程安全输出类SecuredTimableOutput也保证了输出的安全

第七次作业总结

模拟一个多线程实时电梯系统。横向电梯在不同楼座有开关门限制;可动态增加横向、纵向电梯,且对纵向电梯的运行速度、可容纳人数,横向电梯的运行速度、可容纳人数、可开关门信息进行定制;乘客的请求限制仅楼座和楼层不会同时相同,新增换乘需求。

共享对象

Checkend类的checkend,PersonRequests类的allLongDisPersonRequests、allCirdisPersonRequests,为了最优分配环向电梯和纵向电梯还需要共享电梯数量所以有ArrayList<LongitudinalDispatcher> allLongDisarray和ArrayList<CircumferentialDispatcher> allCirDisarray,为了检测请求是否完全完成创建了PersonRequests类的allPersonRequest

同步块的设置或锁的选择

在本次作业是在第六次作业上进行了功能添加,同样没有使用同步块方法,使用的是ReentrantReadWriteLock,放弃使用了sychronized关键字,唯一使用sychronized的类是线程安全输出类SecuredTimableOutput

为了防止轮询我并没有使用wait()和 notify()方法,而是通过sleep()线程防止轮询CPU过多占用

|- Main:主类
|- Checkend:读入线程与调度器交互的共享对象
|- CircumferentialDispatcher:环向电梯调度器线程
|- LongitudinalDispatcher:纵向电梯调度器线程
|- PersonRequests:电梯内外的队列。作为电梯外的队列,是调度器与电梯交互的共享对象。
|- Elevator:电梯线程
|- SecureTimableOutput:线程安全输出

 

 

bug

在本次作业中的强测有5个RTLE,在互测中被hack了一次,其原因都是同一层有两个以上电梯但是环向电梯有不同的可停靠楼座,忘记判断请求是否可达

bug修复

for (int i = personRequests.size() - 1, cnt = 0; i >= 0; i--) {
               PersonRequest personRequest =
                      (PersonRequest) ((LinkedList<?>) personRequests.getPersonRequests()).get(i);
               if (switchinfo[personRequest.getToBuilding() - 'A'] != 1) {
                   continue;
              }
               if (personRequest.getFromBuilding() == nowbuilding) {
                   //同向
                   if (chart[nowbuilding - 'A'][tobuilding - 'A'] > 0
                           && chart[nowbuilding - 'A'][personRequest.getToBuilding() - 'A'] > 0
                           && circumferentialElevator.getPiggyBack().size()
                           < circumferentialElevator.getcapacity()
                           && cnt < personmaxcnt) {
                       circumferentialElevator.in(personRequest);
                       circumferentialElevator.getPiggyBack().add(personRequest);
                      ((LinkedList<?>) personRequests.getPersonRequests()).remove(i);
                       cnt++;
                  } else if (chart[nowbuilding - 'A'][tobuilding - 'A'] < 0
                           && chart[nowbuilding - 'A'][personRequest.getToBuilding() - 'A'] < 0
                           && circumferentialElevator.getPiggyBack().size()
                           < circumferentialElevator.getcapacity()
                           && cnt < personmaxcnt) {
                       circumferentialElevator.in(personRequest);
                       circumferentialElevator.getPiggyBack().add(personRequest);
                      ((LinkedList<?>) personRequests.getPersonRequests()).remove(i);
                       cnt++;
                  }
              }
          }

hack策略

三次作业的测试数据主要都是自己手动构造,主要集中在规定时间范围内的最后一秒投入大量请求,以及大量不同楼层楼座的请求同时到达同一楼座楼层

心得体会

本单元成绩相比于上一单元有所提高,存在bug主要是因为没有充足的时间对自己的代码进行测试,导致的bug与多线程无关,本单元最大的收获自然是如何使用多线程,如何实现线程安全,下一单元要腾出时间多做测试 !