tuchun 2008-11-21 10:34
浏览 180
已采纳

服务器如何处理大量的计时任务。。。

目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有1000-2000个。服务器为非web应用。
[b]问题补充:[/b]
目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有1000-2000个。服务器为非web应用。


呵呵 被jasongreen看出来了 确实是gameserver.改怎么处理好呢?

[b]问题补充:[/b]
目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有1000-2000个。服务器为非web应用。

问题补充:

呵呵 被jasongreen看出来了 确实是gameserver.改怎么处理好呢?

[b]问题补充:[/b]
问题已经解决了。
[code="java"]

import java.util.concurrent.ArrayBlockingQueue;

/**
*

  • @version 2008-11-22

    */
    public class TestMain {

    public static void main(String[] args) throws InterruptedException {

    //计时队列
    ArrayBlockingQueue<TimerTask> queue1 = new ArrayBlockingQueue<TimerTask>(1000, true);
    
    //处理队列
    ArrayBlockingQueue<TimerTask> queue2 = new ArrayBlockingQueue<TimerTask>(1000, true);
    
    //可以增加CheckThread DisposeThread线程进一步提高处理速度 降低延迟
    Thread t1 = new Thread(new AddThread(queue1));
    Thread t2 = new Thread(new CheckThread(queue1, queue2));
    Thread t3 = new Thread(new DisposeThread(queue2, new TestMain()));
    
    t1.start();
    t2.start();
    t3.start();
    

    }

    public void test(){
    System.out.println("dddddddddddddddddddd");
    }

}

/**

  • 此线程添加新的计时任务到计时队列
    */
    class AddThread implements Runnable {

    private ArrayBlockingQueue queue;

    public AddThread(ArrayBlockingQueue queue) {

    this.queue = queue;
    

    }

    public void run() {

    while (true) {
        for (int i = 0; i < 500; i++) {
            int time = 0;
            if(i%3==0){
                time = 60*1000;
            }else if(i%3==1){
                time = 2*60*1000;
            }else if(i%3==2){
                time = 5*60*1000;
            }
            TimerTask tt = new TimerTask(i, System.currentTimeMillis() + time);
            try {
                queue.put(tt);
                //                  System.out.println("添加计时任务" + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(10 * 60 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    }
    }

/**

  • 此线程扫描计时任务队列,检查计时是否完成
    */
    class CheckThread implements Runnable {

    ArrayBlockingQueue queue1;
    ArrayBlockingQueue queue2;

    public CheckThread(ArrayBlockingQueue queue1, ArrayBlockingQueue queue2) {

    this.queue1 = queue1;
    this.queue2 = queue2;
    

    }

    public void run() {

    while (true) {
        for (int i = 0; i < 100; i++) {
            TimerTask tt = null;
            try {
                tt = queue1.take();
                //              System.out.println("检查计时任务" + tt.getRoleID());
                if (tt.getEndTime() <= System.currentTimeMillis()) {
                    //                  System.out.println("添加执行任务" + tt.getRoleID());
                    queue2.put(tt);
                } else {
                    queue1.put(tt);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    

    }
    }

/**

  • 此线程从计时任务完成的队列中不断取出计时任务并执行逻辑
    */
    class DisposeThread implements Runnable {

    TestMain tm;

    ArrayBlockingQueue queue2;

    public DisposeThread(ArrayBlockingQueue queue2,TestMain tm) {

    this.queue2 = queue2;
    this.tm = tm;
    

    }

    public void run() {

    while (true) {
        TimerTask tt = null;
        try {
            tt = queue2.take();
            System.out.println("提取处理任务" + tt.getRoleID());
            tm.test();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (tt != null) {
            System.out.println(tt.getRoleID() + ":" + (tt.getEndTime() - System.currentTimeMillis()));
        }
    }
    

    }
    }

/**

  • 计时任务
    */
    class TimerTask {

    private Integer roleID;

    private Long endTime;

    public TimerTask(Integer roleID, Long endTime) {

    this.roleID = roleID;
    this.endTime = endTime;
    

    }

    public Integer getRoleID() {

    return roleID;
    

    }

    public void setRoleID(Integer roleID) {

    this.roleID = roleID;
    

    }

    public Long getEndTime() {

    return endTime;
    

    }

    public void setEndTime(Long endTime) {

    this.endTime = endTime;
    

    }
    }

[/code]

  • 写回答

6条回答 默认 最新

  • iteye_250 2008-11-21 12:00
    关注

    不知道楼上从什么方面觉得不应该用Timer。

    我认为用Timer完全没问题的。做过一个类似的东西,但是没有1000+这样的规模。
    主要思想就是把所有的客户请求和他们指定的时间放到一个容器。每隔几秒遍历这个容器,判断哪些是可以操作了,把需要操作的记录移出来,启动新线程处理这些记录。有新的请求就实时增加到容器里。

    另外wow的那个cooldown是客户端实现的,你如果知道打断宏是怎么回事就明白了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 找人不需要人工智能回答的gamit解算后做形变分析
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥15 统计大规模图中的完全子图问题
  • ¥15 使用LM2596制作降压电路,一个能运行,一个不能
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题
  • ¥15 ogg dd trandata 报错