ScheduledThreadPoolExecutor меняет задачи в режиме реального времени - PullRequest
0 голосов
/ 14 января 2012

Я использую класс ScheduledThreadPoolExecutor для планирования выполнения задач каждые 30 или 60 секунд, как показано в коде ниже. Я хочу иметь возможность изменить задачу, которая будет выполняться в «реальном времени» на основе значения переменной th isRmi, но я не могу заставить ее работать. В начале моего приложения переменная устанавливается на основе пользовательского ввода, но даже если я изменяю ее во время выполнения программы, она все равно выполняет ту же задачу. Вы можете мне помочь?

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

Ответы [ 2 ]

1 голос
/ 14 января 2012

Вместо планирования двух разных задач (P2P и RMI) запланируйте одну (P2POrRMI), которая на основании значения переменной isRMI выполняет то, что выполняет задача P2P, или то, что выполняет задача RMI.Вы должны иметь возможность создать эту задачу P2POrRMI, просто делегировав RMI или 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);

Убедитесь, что правильно синхронизировали доступ к isRMI или сделали его энергозависимым, так как он будет установлен одним потокоми прочитанный другим (поток планировщика)

0 голосов
/ 14 января 2012

Я подозреваю, что у вас есть некоторые проблемы с видимостью памяти, попробуйте:Проблема заключается в том, что в многопоточной среде изменения, внесенные в переменную в одном потоке, могут быть не сразу (или никогда!) Видимыми для других потоков.volatile делает все изменения видимыми сразу для каждого потока.

Вы также можете использовать AtomicBoolean.

...