Is there a code to check if a timer is running?

2020-04-02 10:00发布

问题:

I have a game where I am scheduling a timer. I have this CoresManager file:

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() {

}
}

I am using this inside the game:

    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);
}

The CoresManager Timer stops running if the player logs out AND the server gets rebooted. To make it run again, I added a code to make it do startTimer() again once you log back in. However, since the timer still runs if the server didn't log out, the timer starts running twice. The Timer starts getting subtracted by 2, or more, depending on how many times you log out and in. I figure that it would fix if there was a code to determine if the timer is already running. Is there a way to do this? Please help!

回答1:

I don't see anything in the documentation that provides for checking the status on a TimerTask object (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/TimerTask.html) so one option would be to extend TimerTask and create your own class. Instead of using an anonymous TimerTask, you could create something along the lines of:

public 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;
    }
}

and just maintain a reference to this CoresTimerTask object, which you then pass into startTimer(). You can then later check this object via hasRunStarted.



回答2:

public long scheduledExecutionTime()

Returns the scheduled execution time of the most recent actual execution of this task. (If this method is invoked while task execution is in progress, the return value is the scheduled execution time of the ongoing task The return value is undefined if the task has yet to commence its first execution.

This method is typically not used in conjunction with fixed-delay execution repeating tasks, as their scheduled execution times are allowed to drift over time, and so are not terribly significant.

  1. first thing periodically running tasks need set/reset state flag
  2. second (when i look at examples) it is better to seal this type of class

but if someone insist to have such methods

   public abstract class NonInterruptableTask extends TimerTask {

        protected boolean isDone = false;

        public boolean isDone() {return isDone;}

        protected abstract void doTaskWork();

        @Override
        public void run() {
            isDone = false;
            doTaskWork();
            isDone = true;
        }

  }

usage:

  TimerTask myTask = new NonInterruptableTask() {

       @Override 
       public void doTaskWork() {

          //job here 
       }
  };


回答3:

you could also declare a boolean state called like "timerstate" or whatever and make it by default to be false. whenever you start a timer you could change this boolean to true and you'd be able to keep track of the timer.

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
                          }
                      }
          }


标签: java timer