我有一个游戏,我正在安排一个计时器。我有这个CoresManager文件:
package com.rs.cores;
import java.util.Timer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public final class CoresManager {
protected static volatile boolean shutdown;
public static WorldThread worldThread;
public static ExecutorService serverWorkerChannelExecutor;
public static ExecutorService serverBossChannelExecutor;
public static Timer fastExecutor;
public static ScheduledExecutorService slowExecutor;
public static int serverWorkersCount;
public static void init() {
worldThread = new WorldThread();
int availableProcessors = Runtime.getRuntime().availableProcessors();
serverWorkersCount = availableProcessors >= 6 ? availableProcessors - (availableProcessors >= 12 ? 7 : 5) : 1;
serverWorkerChannelExecutor = availableProcessors >= 6 ? Executors
.newFixedThreadPool(availableProcessors - (availableProcessors >= 12 ? 7 : 5),
new DecoderThreadFactory()) : Executors.newSingleThreadExecutor(new DecoderThreadFactory());
serverBossChannelExecutor = Executors
.newSingleThreadExecutor(new DecoderThreadFactory());
fastExecutor = new Timer("Fast Executor");
slowExecutor = availableProcessors >= 6 ? Executors.newScheduledThreadPool(availableProcessors >= 12 ? 4 : 2,
new SlowThreadFactory()) : Executors
.newSingleThreadScheduledExecutor(new SlowThreadFactory());
worldThread.start();
}
public static void shutdown() {
serverWorkerChannelExecutor.shutdown();
serverBossChannelExecutor.shutdown();
fastExecutor.cancel();
slowExecutor.shutdown();
shutdown = true;
}
private CoresManager() {
}
}
我在游戏中使用它:
private void startTimer() {
CoresManager.fastExecutor.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (timer == 0 || timer < 1) {
player.sm("Your timer has ended! The NPCs will no longer spawn.");
timer = 0;
this.cancel();
exitInstance();
return;
}
timer--;
timerchecker = true;
seconds = timer % 60;
player.setTimer(timer);
minutes = TimeUnit.SECONDS.toMinutes(timer);
}
}, 0, 1000);
}
如果播放器注销并且服务器重新启动,CoresManager Timer将停止运行。为了让它再次运行,我添加了一个代码,使它在重新登录后再次执行startTimer()。但是,由于如果服务器没有注销,计时器仍然运行,计时器开始运行两次。计时器开始被减去2或更多,具体取决于你注销和进入的次数。我认为如果有一个代码来确定计时器是否已经运行,它将会修复。有没有办法做到这一点?请帮忙!
答案 0 :(得分:13)
我没有在文档中看到任何用于检查TimerTask对象(http://docs.oracle.com/javase/1.5.0/docs/api/java/util/TimerTask.html)状态的内容,因此一个选项是扩展TimerTask并创建自己的类。您可以创建以下内容:
,而不是使用匿名TimerTaskpublic class CoresTimerTask extends TimerTask {
private boolean hasStarted = false;
@Overrides
public void run() {
this.hasStarted = true;
//rest of run logic here...
}
public boolean hasRunStarted() {
return this.hasStarted;
}
}
并保持对此CoresTimerTask对象的引用,然后将其传递给startTimer()。然后,您可以通过hasRunStarted检查此对象。
答案 1 :(得分:0)
public long scheduledExecutionTime()
返回此任务最近实际执行的计划执行时间。 (如果在任务执行过程中调用此方法,则返回值是正在进行的任务的计划执行时间如果任务尚未开始首次执行,则返回值未定义。
此方法通常不与固定延迟执行重复任务一起使用,因为它们的计划执行时间允许随时间漂移,因此不是非常重要。
但如果有人坚持要有这样的方法
public abstract class NonInterruptableTask extends TimerTask {
protected boolean isDone = false;
public boolean isDone() {return isDone; }
protected abstract void doTaskWord();
@Override
public void run() {
isDone = false;
doTaskWord();
isDone = true;
}
}
TimerTask myTask = new NonInterruptableTask() {
@Override
public void doTimerWork() {
//job here
}
};
答案 2 :(得分:0)
您还可以声明一个称为“ timerstate”的布尔状态或其他任何值,并默认将其设置为false。每当您启动计时器时,都可以将此布尔值更改为true,这样就可以跟踪计时器。
public boolean timerstate;
public Timer t1;
// some code goes here to do whatever you want
if(timerstate == true) {
t1.cancel();
t1.purge();
t1 = new Timer();
} else{
t1.schedule(new TimerTask() {
@Override
public void run() {
timerstate = true;
//rest of code for the timer goes here
}
}
}