1.功能要求

实验室有固定台数的设备供学生通过网络连接进行实验,一台设备只能同时被一个用户使用,一个用户只能占用一台设备。

下面是一个功能的简图:

2.实现方案

2.1 初始化

在项目启动之后,开始进行实验设备排队功能的初始化,需要初始化的有:

a,新建用于存放设备的队列,并从数据库中查出所有可正常使用的设备放入队列中;

b,新建一个用于排队的线程池,后面会说明用途;

c,新建一个用于存放排队用户的队列。

2.2 流程实现

Thread :当前的用户的请求线程;waitUsers:存放排队用户线程的队列;Exec:排队的线程池;threadA:在线程池中开启的排队线程;Equipment:存放设备的线程

3.具体实现

3.1.队列初始化

1 /**

2 * 初始化队列及线程池3 *@authoryangc4 *5 */

6 public classEquipmentQueue {7 //设备队列

8 public static BlockingQueueequipment;9 //请求队列

10 public static BlockingQueuewaitUsers;11 //线程池

12 public staticExecutorService exec;13

14 /**

15 * 初始化设备、请求队列及线程池16 */

17 public voidinitEquipmentAndUsersQueue(){18 exec =Executors.newCachedThreadPool();19 equipment=new LinkedBlockingQueue();20 //将空闲的设备放入设备队列中

21 setFreeDevices(exec);22 waitUsers=new LinkedBlockingQueue();23 }24

25 /**

26 * 将空闲的设备放入设备队列中27 *@paramexec28 */

29 private voidsetFreeDevices(ExecutorService exec) {30 //获取可用的设备

31 List equipments=getFreeEquipment();32 for (int i = 0; i < equipments.size(); i++) {33 Record dc=equipments.get(i);34 Equipment de=new Equipment(dc.getInt("id"),dc.getStr("quip_no"),dc.getStr("name"));35 try{36 equipment.put(de);37 } catch(InterruptedException e) {38 e.printStackTrace();39 }40 }41 }42

43 /**

44 * 获取可用的设备(从数据库中查出可用的设备)45 *@return

46 */

47 public ListgetFreeEquipment(){48 returnQuipPartsManager.manager.getFreeEquipment();49 }50 }

3.2.过滤实验请求

当用户的实验请求进入时,首先要判断用户在数据库中是否处于未退出的情况,如果处于未退出的状态,将状态改为已结束,然后重新进行排队。

每次请求实验时,会在数据库中保存一条排队数据,记录排队的用户、状态、使用时间等等信息。WaitUser是实验请求对应的类,主要字段有:Thread(存放实验请求的线程对象)、Session(实验请求对应的用户session)、Test(数据库中排队数据对应的类)。当请求进入后会在过滤器中将用户的请求对象放入到用请求队列中。

1 //判断当前的用户是否有未退出的实验并进行处理

2 TestManager.manager.setUserTestInfomation(session);3 //获取当前的线程

4 Thread thread=Thread.currentThread();5 //将当前用户为等待

6 Test test=TestManager.manager.SetUserTestStateForWait(session);7 //创建当前的用户请求对象

8 WaitUser waitUser=newWaitUser();9 waitUser.setThread(thread);10 waitUser.setSession(session);11 waitUser.setTest(test);12 //将当前用户请求对象放入队列中

13 EquipmentQueue.waitUsers.add(waitUser);

3.3.执行排队线程并挂起当前线程

在线程池中分配一个线程给当前的请求,并运行此线程,然后将请求线程挂起。

1 //在线程池中给当前的用户请求分配线程,运行等待分配设备

2 EquipmentQueue.exec.execute(waitUser);3 //暂停当前的用户请求,当whetherWait等于2时,说明设备绑定已经完成,无需将当前线程挂起

4 synchronized(thread){5 if(waitUser.getWhetherWait()!=2){6 thread.wait();7 }8 }

开始排队即运行WaitUser中的experiment方法,先从设备队列中获取一个设备,如果没有设备,当前线程将会进入堵塞状态,直到队列中放入设备;如果有设备,从请求队列中取出一个请求对象,设置请求与设备绑定。

1 public class WaitUser implementsRunnable{2 //当前请求的线程对象

3 privateThread thread;4 //当前用户的session对象

5 privateHttpSession session;6 //用于判断线程是否进入wait状态

7 private int whetherWait=0;8 //用户的实验对象

9 privateTest test;10

11 @Override12 public voidrun() {13 //当线程未中断时

14 while(!Thread.interrupted()){15 experiment();16 }17 }18

19 /**

20 * 将实验信息存入数据库,用户信息从session获取,将使用的设备从队列中删除,将设备对象存入session21 */

22 public voidexperiment(){23 try{24 //取出一个设备

25 Equipment equipment=EquipmentQueue.equipment.take();26 EquipmentQueue.equipment.remove(equipment);27 WaitUser waitUser=EquipmentQueue.waitUsers.take();28 EquipmentQueue.waitUsers.remove(waitUser);29 //将设备与用户绑定,状态设置为试验中

30 TestManager.manager.bindUserAndEquipment(equipment,waitUser);31 } catch(InterruptedException e) {32 System.err.println("---" +e.getMessage());33 }34 }35

36

37 publicTest getTest() {38 returntest;39 }40

41 public voidsetTest(Test test) {42 this.test =test;43 }44

45 public intgetWhetherWait() {46 returnwhetherWait;47 }48

49 public void setWhetherWait(intwhetherWait) {50 this.whetherWait =whetherWait;51 }52

53 publicHttpSession getSession() {54 returnsession;55 }56

57 public voidsetSession(HttpSession session) {58 this.session =session;59 }60

61 publicThread getThread() {62 returnthread;63 }64

65 public voidsetThread(Thread thread) {66 this.thread =thread;67 }68

69 }

WaitUser

3.4.释放请求线程

当设备绑定成功后,即可释放请求线程,这里有一个需要注意的问题,挂起请求线程与释放请求线程的先后关系(确保不会出现先释放后挂起的情况),把释放与挂起线程放到用显式锁修饰的代码块中,确保同时只会执行一处。当释放锁之后将状态WhetherWait的值设为2,标记此请求已经与设备绑定,不需要挂起。

1 Thread thread=waitUser.getThread();2 synchronized(thread) {3 waitUser.setWhetherWait(2);4 thread.notify();5 }

4.补充

4.1.排队时,给予客户端的反馈

每次请求实验会存入一条排队数据到数据库中,当完成设备绑定后会将排队数据的状态值设置为“正在使用”,可以在客户端执行一个定时任务,定时从数据库查询处于“排队中”的请求数量,这样就可以在客户端实时显示“排队中,您前面还有10位用户正在等待...”的效果。

4.2.用户进入实验后,长时间暂用而不使用的情况处理

当用户进入实验后,为防止用户长时间的占用实验设备(并没有在使用),需要执行一个定时任务,每间隔一段时间,弹窗确认用户是否在使用,如果用户没有回应,则视为用户已经离开,将用户与设备解绑并退出实验。

4.3.用户强行退出的处理(关闭页面/管理浏览器/关闭电脑...强行退出实验的情况)

当用户强行退出时,在数据库中用户与设备依然处于绑定状态。当用户进入实验后,需要在客户端执行一个定时任务,实时的更新用户的最新实验时间。然后在服务端运行一个定时任务,实时检查数据库中的排队数据,判断状态为“正在使用”的数据中是否有最新的实验时间与当前时间的差值是否大于客户端定时任务的间隔时间(考虑到时间的更新会有一定的延迟,可以适当留些余量)的数据,如果大于则设备与用户解绑。

原文:http://www.cnblogs.com/yangc/p/7699259.html

java 排队实现_实验排队功能实现(JAVA)相关推荐

  1. java 排队_实验排队功能实现(JAVA)

    1.功能要求 实验室有固定台数的设备供学生通过网络连接进行实验,一台设备只能同时被一个用户使用,一个用户只能占用一台设备. 下面是一个功能的简图: 2.实现方案 2.1 初始化 在项目启动之后,开始进 ...

  2. java布道师_初探第10代Java帝国:11位Java专家道出了他们最喜欢的功能

    Java 10发布后.我们第一时间与11位Java专家讨论了一波.顺便深入挖掘了他们在Java 10中最喜欢的功能和对未发布的JDK11版本的一些看法. " Java 10对Java 9来说 ...

  3. 软件工程 c java的联系_软件工程—WC功能实现 (JAVA)

    软件工程-WC功能实现(JAVA) 项目要求 ​ wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某 ...

  4. java coin介绍_代码示例中的Java 7:Project Coin

    java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...

  5. java 安全包_信息加密系统设计(依托Java平台安全包)

    这是加密系统设计的一个示例 一.目的与要求 (一)目的 通过实践,了解运用相应密码算法,设计并实现一个加密系统的全过程,掌握设计和实现信息安全系统的基本手段和常用方法,提高学生的动手能力和分析.解决问 ...

  6. java商品销售_商品销售系统(Java).doc

    淮海工学院计算机工程学院 实验报告书 课程名:<面向对象程序设计> 实验名称: Java深入面向对象编程 商品销售系统 班 级: 软件081 组 长: 组 员: 李宏志. 谢超 一.实验目 ...

  7. java 故障排查_目前最全的 Java 服务问题排查套路

    问题分类: CPU问题 内存问题(GC问题.内存泄漏. OOM,Coredump 等) I/O问题 问题排查工具箱: 系统级别的工具: top:查看系统/进程cpu.内存.swap等资源占用情况的必备 ...

  8. java lock 效率_工作常用4种Java线程锁的特点,性能比较、使用场景

    多线程的缘由 在出现了进程之后,操作系统的性能得到了大大的提升.虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求. 使用多线程的理由之一是和进程相比,它是一种非常花 ...

  9. java 优先队列 用法_优先队列的基本用法(java和c++)

    #include #define ll long long #define mod 1000000007 using namespace std; //熟悉一下优先队列的基本用法 int main() ...

最新文章

  1. 基于OpenCV的条形码区域分割
  2. Firefox下载自动保存
  3. 上海实验学校计算机等级考试,全国和上海的计算机等级考试一级内容差别?
  4. Linux chmod命令修改文件与文件夹权限的命令附实例
  5. android 固定大小,android 固定大小取图片缩略图
  6. 《leetcode》pascals-triangle(杨辉三角)
  7. Lucene 和 ElasticSearch 的前世今生
  8. 树莓派安装摄像头、耳机、话筒
  9. 如何系统的自学python-如何系统地自学Python?
  10. mysql web客户端_mycli--让你惊艳的mysql客户端
  11. 中国移动企业文化考试试题含答案
  12. C# 读取PDF书签内容
  13. H5+CSS3面试题
  14. ECSHOP二次开发之心得体验
  15. 微信小程序仿今日头条小程序端界面和代码演示
  16. 深入了解示波器(三):示波器的带宽
  17. 【转】Android Protobuf应用及原理
  18. 天下没有不会这么回事!不会就学——北漂18年(28)
  19. 解析身份证号码(Python版)
  20. UDS诊断故障码及诊断服务介绍(14h, 19h, 85h)

热门文章

  1. 【BZOJ3238】差异,后缀数组+单调栈维护height
  2. flask web开发是前端还是后端_Flask Web开发实战:入门、进阶与原理解析 PDF 全格式版...
  3. 两个服务器之间怎么传输大量数据速度快 java socket_千兆网络的传输速度能超过125MB/s么?...
  4. bzoj2424 [HAOI2010]订货 费用流
  5. 苹果css攻击,研究人员设计了一种新的CSS和HTML攻击 导致iPhone重启或冻结Mac
  6. 用php写的亲亲鲜花网站_php54鲜花销售网站
  7. Unity Shader:用几何着色器实现复联3灭霸的终极大招灰飞烟灭
  8. Vue2.0 + ElementUI 手写权限管理系统后台模板(三)——页面搭建
  9. 管道符和作业控制 shell变量 环境变量配置文件
  10. MySQL半同步的配置