Search code examples
javarmi

ScheduledThreadPoolExecutor changing tasks in real time


I'm using the ScheduledThreadPoolExecutor class to schedule tasks to run every 30 or 60 seconds like the code below shows. I want to be able to change the task to be executed in "real time" based on the value of th isRmi variable but i can't seem to get it to work. At the beginning of my application the variable is set based on user input but even if i change it during the program's execution it still executes the same task. Can you help me?

   public void execute() {

        ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(3);

        scheduler.scheduleAtFixedRate(new ServPresTimer(player), 0, 30, TimeUnit.SECONDS);

        if (!isRMI) {
            scheduler.scheduleAtFixedRate(new P2PTimer(player), 1, 60, TimeUnit.SECONDS);
        } else {
            scheduler.scheduleAtFixedRate(new RMITimer(player), 1, 60, TimeUnit.SECONDS);
        }
    }

Solution

  • Instead of scheduling two different tasks (P2P and RMI), schedule a single one (P2POrRMI) which, based on the value of the isRMI variable, executes what the P2P task executes, or what the RMI task executes. You should be able to create this P2POrRMI task by just delegating to RMI or P2P:

    public class P2POrRMITimer implements Runnable {
        private Runnable p2p;
        private Runnable rmi;
        private ObjectWhichContainsTheFlag flagContainer;
    
        public P2POrRMITimer(Runnable p2p, 
                             Runnable rmi, 
                             ObjectWhichContainsTheFlag flagContainer) {
            this.p2p = p2p;
            this.rmi = rmi;
            this.flagContainer = flagContainer;
        }
    
        @Override
        public void run() {
            if (flagContainer.isRmi()) {
                rmi.run();
            }
            else {
                p2p.run();
            } 
        }
    }
    
    ...
    
    scheduler.scheduleAtFixedRate(new P2POrRMITimer(new P2PTimer(player),
                                                    new RMITimer(player),
                                                    this),
                                  1, 
                                  60, 
                                  TimeUnit.SECONDS);
    

    Make sure to properly synchronize the access to isRMI, or to make it volatile, since it will be set by one thread, and read by another one (the scheduler thread)