tuchun
2008-11-21 10:34 阅读 164
已采纳

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

目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有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 iteye_250 2008-11-21 12:00

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

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

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

    点赞 评论 复制链接分享
  • iteye_250 iteye_250 2008-11-21 11:15

    服务器端用Timer实现守护进程处理每个客户端的请求。
    通信的话可以用servlet,看你的服务器支持不支持了。

    点赞 评论 复制链接分享
  • iteye_19907 iteye_19907 2008-11-21 11:16

    你这个造型很像是要做gameserver啊?

    点赞 评论 复制链接分享
  • iteye_19907 iteye_19907 2008-11-21 11:17

    很明显不应该用Timer

    点赞 评论 复制链接分享
  • iteye_19907 iteye_19907 2008-11-21 11:18

    同时计时1000~2000,其实计时这玩意就跟魔兽世界的cooldown差不多, startTime,duration,endTime

    点赞 评论 复制链接分享
  • iteye_19907 iteye_19907 2008-11-21 13:29

    举个例子:ogame。
    cooldown = {计时关键字,开始时间,总时间}
    一个cooldown数组
    每帧遍历cooldown数组,拿当前时间-开始时间。针对每个计时关键字的计时状态也就出来了。

    点赞 评论 复制链接分享

相关推荐