目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有1000-2000个。服务器为非web应用。
[b]问题补充:[/b]
目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有1000-2000个。服务器为非web应用。
[b]问题补充:[/b]
目前需求有大量的计时任务,但限制不可能在客户端进行计时。
所以服务器要处理每个客户端的计时请求,每个客户端指定的时间到了之后
服务器要处理相应的事情,显然为每一个客户端开一个计时任务是不合适的。
在这里问一下,大家有什么好的方案来处理呢? 同时计时的任务可能有1000-2000个。服务器为非web应用。
[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]
不知道楼上从什么方面觉得不应该用Timer。
我认为用Timer完全没问题的。做过一个类似的东西,但是没有1000+这样的规模。
主要思想就是把所有的客户请求和他们指定的时间放到一个容器。每隔几秒遍历这个容器,判断哪些是可以操作了,把需要操作的记录移出来,启动新线程处理这些记录。有新的请求就实时增加到容器里。
另外wow的那个cooldown是客户端实现的,你如果知道打断宏是怎么回事就明白了。
服务器端用Timer实现守护进程处理每个客户端的请求。
通信的话可以用servlet,看你的服务器支持不支持了。
你这个造型很像是要做gameserver啊?
很明显不应该用Timer
同时计时1000~2000,其实计时这玩意就跟魔兽世界的cooldown差不多, startTime,duration,endTime
举个例子:ogame。
cooldown = {计时关键字,开始时间,总时间}
一个cooldown数组
每帧遍历cooldown数组,拿当前时间-开始时间。针对每个计时关键字的计时状态也就出来了。