利用ArrayBlockingQueue实现大量计时任务计时

最近在做一个socket通讯的项目,项目中有个需求:根据客户端的请求记时,计时时间不定。

由于考虑到安全等因素,决定将所有客户端计时任务放在服务器端。最大同时计时任务需求为500个。

如果采用timer为每个任务计时,肯定不现实(服务器线程消耗严重)。出了这个考虑之外,还要考虑多线程线程安全的因素。

基于这些,我用到了ArrayBlockingQueue来实现。ArrayBlockingQueue是一个阻塞的同步队列,具体参考JDK文档。

主要思想是一个ArrayBlockingQueue来保存计时队列 一个ArrayBlockingQueue来保存计时完成要处理的队列。

一个线程不断扫描计时队列,检测时间是否到了,到了就添加到处理队列,由另外的线程来处理逻辑任务。

实现代码:

  1. package test.client;
  2. import java.util.concurrent.ArrayBlockingQueue;
  3. /**
  4.  *
  5.  * @version 2008-11-22          
  6.  */
  7. public class TestMain {
  8.     public static void main(String[] args) throws InterruptedException {
  9.         //计时队列
  10.         ArrayBlockingQueue<TimerTask> queue1 = new ArrayBlockingQueue<TimerTask>(1000true);
  11.         //处理队列
  12.         ArrayBlockingQueue<TimerTask> queue2 = new ArrayBlockingQueue<TimerTask>(1000true);
  13.         //可以增加CheckThread DisposeThread线程进一步提高处理速度 降低延迟
  14.         Thread t1 = new Thread(new AddThread(queue1));
  15.         Thread t2 = new Thread(new CheckThread(queue1, queue2));
  16.         Thread t3 = new Thread(new DisposeThread(queue2, new TestMain()));
  17.         t1.start();
  18.         t2.start();
  19.         t3.start();
  20.     }
  21. }
  22. /**
  23.  * 此线程添加新的计时任务到计时队列
  24.  */
  25. class AddThread implements Runnable {
  26.     private ArrayBlockingQueue<TimerTask> queue;
  27.     public AddThread(ArrayBlockingQueue<TimerTask> queue) {
  28.         this.queue = queue;
  29.     }
  30.     public void run() {
  31.         while (true) {
  32.             for (int i = 0; i < 500; i++) {
  33.                 int time = 0;
  34.                 if(i%3==0){
  35.                     time = 60*1000;
  36.                 }else if(i%3==1){
  37.                     time = 2*60*1000;
  38.                 }else if(i%3==2){
  39.                     time = 5*60*1000;
  40.                 }
  41.                 TimerTask tt = new TimerTask(i, System.currentTimeMillis() + time);
  42.                 try {
  43.                     queue.put(tt);
  44.                     //                  System.out.println("添加计时任务" + i);
  45.                 } catch (InterruptedException e) {
  46.                     e.printStackTrace();
  47.                 }
  48.             }
  49.             try {
  50.                 Thread.sleep(10 * 60 * 1000);
  51.             } catch (InterruptedException e) {
  52.                 e.printStackTrace();
  53.             }
  54.         }
  55.     }
  56. }
  57. /**
  58.  * 此线程扫描计时任务队列,检查计时是否完成
  59.  */
  60. class CheckThread implements Runnable {
  61.     ArrayBlockingQueue<TimerTask> queue1;
  62.     ArrayBlockingQueue<TimerTask> queue2;
  63.     public CheckThread(ArrayBlockingQueue<TimerTask> queue1, ArrayBlockingQueue<TimerTask> queue2) {
  64.         this.queue1 = queue1;
  65.         this.queue2 = queue2;
  66.     }
  67.     public void run() {
  68.         while (true) {
  69.             for (int i = 0; i < 100; i++) {
  70.                 TimerTask tt = null;
  71.                 try {
  72.                     tt = queue1.take();
  73.                     //              System.out.println("检查计时任务" + tt.getRoleID());
  74.                     if (tt.getEndTime() <= System.currentTimeMillis()) {
  75.                         //                  System.out.println("添加执行任务" + tt.getRoleID());
  76.                         queue2.put(tt);
  77.                     } else {
  78.                         queue1.put(tt);
  79.                     }
  80.                 } catch (InterruptedException e) {
  81.                     e.printStackTrace();
  82.                 }
  83.             }
  84.             try {
  85.                 Thread.sleep(100);
  86.             } catch (InterruptedException e) {
  87.                 e.printStackTrace();
  88.             }
  89.         }
  90.     }
  91. }
  92. /**
  93.  * 此线程从计时任务完成的队列中不断取出计时任务并执行逻辑
  94.  */
  95. class DisposeThread implements Runnable {
  96.     TestMain tm;
  97.     
  98.     ArrayBlockingQueue<TimerTask> queue2;
  99.     public DisposeThread(ArrayBlockingQueue<TimerTask> queue2,TestMain tm) {
  100.         this.queue2 = queue2;
  101.         this.tm = tm;
  102.     }
  103.     public void run() {
  104.         while (true) {
  105.             TimerTask tt = null;
  106.             try {
  107.                 tt = queue2.take();
  108.                 System.out.println("提取处理任务" + tt.getRoleID());
  109.                 tm.test();
  110.             } catch (InterruptedException e) {
  111.                 e.printStackTrace();
  112.             }
  113.             if (tt != null) {
  114.                 System.out.println(tt.getRoleID() + ":" + (tt.getEndTime() - System.currentTimeMillis()));
  115.             }
  116.         }
  117.     }
  118. }
  119. /**
  120.  * 计时任务
  121.  */
  122. class TimerTask {
  123.     private Integer roleID;
  124.     private Long endTime;
  125.     public TimerTask(Integer roleID, Long endTime) {
  126.         this.roleID = roleID;
  127.         this.endTime = endTime;
  128.     }
  129.     public Integer getRoleID() {
  130.         return roleID;
  131.     }
  132.     public void setRoleID(Integer roleID) {
  133.         this.roleID = roleID;
  134.     }
  135.     public Long getEndTime() {
  136.         return endTime;
  137.     }
  138.     public void setEndTime(Long endTime) {
  139.         this.endTime = endTime;
  140.     }
  141. }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值