Maj*_*ssi 8 java multithreading timer timertask
我正在使用Timer和TimerTask来长时间轮询聊天应用程序的新消息.我想研究两种"略微"不同的可能性:
1:计时器声明为局部变量
public List<MessageBean> getLastMessages(...) {
[...]
Timer timer = new Timer(true); //**Timer declared as local variable**
while (someCondiction) {
MessagesTimerTask returnMessagesTask = new MessagesTimerTask([...]);
timer.schedule(returnMessagesTask, 6000);
synchronized (listMessageBean) {
listMessageBean.wait();
//notify is called in the MessagesTimerTask which extends TimerTask
}
}
}
Run Code Online (Sandbox Code Playgroud)
*问题:每次调用方法时,我都会看到创建了一个新线程,[Timer-1],[Timer-2]等.在Eclipse Debug窗口中,即使在getLastMessages之后它们似乎都在运行(..)完成运行并将值返回给客户端.如果计时器实际上使用线程,这可能会导致巨大的问题,并且在很少的事务之后,服务器最终会消耗所有的机器资源.
2:定时器声明为本地字段
private final Timer timer = new Timer(true); //**Timer declared as local field**
public List<MessageBean> getLastMessages(...) {
[...]
while (someCondiction) {
MessagesTimerTask returnMessagesTask = new MessagesTimerTask([...]);
timer.schedule(returnMessagesTask, 6000);
synchronized (listMessageBean) {
listMessageBean.wait();
//notify is called in the MessagesTimerTask which extends TimerTask
}
}
}
Run Code Online (Sandbox Code Playgroud)
*问题:每次调用方法时,使用相同的线程[Thread-1],但我不确定是否连续两次调用,后者将取消/覆盖前者(该类是@Autowired by spring )?
有什么建议 ?谢谢.
以下是该方法的源代码schedule:
190 public void schedule(TimerTask task, long delay) {
191 if (delay < 0)
192 throw new IllegalArgumentException("Negative delay.");
193 sched(task, System.currentTimeMillis()+delay, 0);
194 }
Run Code Online (Sandbox Code Playgroud)
和sched方法:
386 private void sched(TimerTask task, long time, long period) {
387 if (time < 0)
388 throw new IllegalArgumentException("Illegal execution time.");
389
390 // Constrain value of period sufficiently to prevent numeric
391 // overflow while still being effectively infinitely large.
392 if (Math.abs(period) > (Long.MAX_VALUE >> 1))
393 period >>= 1;
394
395 synchronized(queue) {
396 if (!thread.newTasksMayBeScheduled)
397 throw new IllegalStateException("Timer already cancelled.");
398
399 synchronized(task.lock) {
400 if (task.state != TimerTask.VIRGIN)
401 throw new IllegalStateException(
402 "Task already scheduled or cancelled");
403 task.nextExecutionTime = time;
404 task.period = period;
405 task.state = TimerTask.SCHEDULED;
406 }
407
408 queue.add(task);
409 if (queue.getMin() == task)
410 queue.notify();
411 }
412 }
Run Code Online (Sandbox Code Playgroud)
从这里可以清楚地看到队列正在用于在内部存储任务,这意味着以后的任务不会覆盖之前的任务.如果您还检查mainLoop文件中的方法,您可以看到它按照计划时间按顺序从队列中获取任务并执行它们.
因此,在同一Timer对象上安排多个任务应该不是问题.
作为一个侧面说明,考虑更换Timer与ScheduledThreadPoolExecutor从Java 1.5中提供.