非活动用户的Java超时

非活动用户的Java超时,java,concurrency,javafx-2,Java,Concurrency,Javafx 2,我的ScheduledThreadPoolExecutor有问题 我需要一个超时,它将在'n'-秒之后重定向到第一页。如果用户输入字符,计时器应再次开始计数,并且可能不会重定向到第一页。 (因此计数器应中止其计划任务) 问题是,计时器会启动,但如果键入密钥,它不会取消计划的任务。将调用stop()-方法。但是scheduledThreadPool.shutdownNow()似乎不起作用 我的TimerClass看起来像这样: public class MyTimer { private

我的
ScheduledThreadPoolExecutor有问题

我需要一个超时,它将在
'n'-秒之后重定向到第一页。如果用户输入字符,计时器应再次开始计数,并且可能不会重定向到第一页。
(因此计数器应中止其计划任务)

问题是,计时器会启动,但如果键入密钥,它不会取消计划的任务。将调用
stop()
-方法。但是
scheduledThreadPool.shutdownNow()似乎不起作用

我的TimerClass看起来像这样:

public class MyTimer {

    private final Runnable logicalWorker;

    private final long delay;

    private final ScheduledThreadPoolExecutor scheduledThreadPool;

    public MyTimer(final Runnable logicalWorker, final long delay) {
        scheduledThreadPool = new ScheduledThreadPoolExecutor(1);
        this.logicalWorker = logicalWorker;
        this.delay = delay;
    }

    public void start() {
        scheduledThreadPool.schedule(logicalWorker, delay, TimeUnit.SECONDS);
    }

    public void stop() {
        scheduledThreadPool.shutdownNow();
        scheduledThreadPool.getQueue().clear();
    }

    public void restart() {
        start();
    }

    public boolean isScheduled() {
        return !scheduledThreadPool.isTerminated() && !scheduledThreadPool.isShutdown();
    }
}
protected void startTimeout() {
    if (currentInstance.getAutoTimeout() != null && currentInstance.getAutoTimeout().isScheduled()) {
        currentInstance.getAutoTimeout().restart();
        return;
    }
    currentInstance.setAutoTimeout(new MyTimer(new Runnable() {

        @Override
        public void run() {
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    if (!PageContent.PAGE_ID.equals(currentInstance.getPageId()) && !forceOpen) {
                        cancelCurrentProcesses();
                        switchPageByPageId(PageContent.PAGE_ID);
                    }
                }
            });
        }
    }, currentInstance.getPageDelay()));
    if (currentInstance.getPageDelay() > 0) {
        currentInstance.getAutoTimeout().start();
    }
}
调用timerClass的超类中的方法如下:

public class MyTimer {

    private final Runnable logicalWorker;

    private final long delay;

    private final ScheduledThreadPoolExecutor scheduledThreadPool;

    public MyTimer(final Runnable logicalWorker, final long delay) {
        scheduledThreadPool = new ScheduledThreadPoolExecutor(1);
        this.logicalWorker = logicalWorker;
        this.delay = delay;
    }

    public void start() {
        scheduledThreadPool.schedule(logicalWorker, delay, TimeUnit.SECONDS);
    }

    public void stop() {
        scheduledThreadPool.shutdownNow();
        scheduledThreadPool.getQueue().clear();
    }

    public void restart() {
        start();
    }

    public boolean isScheduled() {
        return !scheduledThreadPool.isTerminated() && !scheduledThreadPool.isShutdown();
    }
}
protected void startTimeout() {
    if (currentInstance.getAutoTimeout() != null && currentInstance.getAutoTimeout().isScheduled()) {
        currentInstance.getAutoTimeout().restart();
        return;
    }
    currentInstance.setAutoTimeout(new MyTimer(new Runnable() {

        @Override
        public void run() {
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    if (!PageContent.PAGE_ID.equals(currentInstance.getPageId()) && !forceOpen) {
                        cancelCurrentProcesses();
                        switchPageByPageId(PageContent.PAGE_ID);
                    }
                }
            });
        }
    }, currentInstance.getPageDelay()));
    if (currentInstance.getPageDelay() > 0) {
        currentInstance.getAutoTimeout().start();
    }
}
按键监听器和鼠标ClickListener将在开始时通过以下方法在场景中设置:

protected void placePage() throws SecurityException, IllegalArgumentException, IllegalAccessException,
        InstantiationException, NoSuchMethodException, InvocationTargetException {
    startTimeout();
    currentInstance.getRoot().setOnMouseClicked(new EventHandler<MouseEvent>() {

        @Override
        public void handle(MouseEvent arg0) {
            startTimeout();
        }
    });
    currentInstance.getRoot().setOnKeyReleased(new EventHandler<KeyEvent>() {

        @Override
        public void handle(KeyEvent arg0) {
            startTimeout();
        }
    });
}
protectedvoid placePage()引发SecurityException、IllegalArgumentException、IllegalAccessException、,
实例化异常、NoSuchMethodException、InvocationTargetException{
startTimeout();
currentInstance.getRoot().setOnMouseClicked(新建EventHandler()){
@凌驾
公共无效句柄(MouseEvent arg0){
startTimeout();
}
});
currentInstance.getRoot().setOnKeyReleased(新的EventHandler()){
@凌驾
公共无效句柄(KeyEvent arg0){
startTimeout();
}
});
}
看看这个->

shutdownNow()
不保证取消执行

至于解决方案,我建议您使用
ScheduledFuture
Future
对象,而不是
Runnable

[编辑]您可以调用
.cancel()
函数而不是
.shutdownNow()
函数的计划的未来,由您调用的
.schedule()
调用返回,但似乎没有使用(或确实保存)未来
的句柄。是的,您仍然需要一个
可运行的
,但仅限于它将为您提供
未来
句柄

试着这样做:

private ScheduledFuture<?> future;
public void start() {
    future = scheduledThreadPool.schedule(logicalWorker, delay, TimeUnit.SECONDS);
}
public void stop() {
    if(future != null) future.cancel();
}
private ScheduledFuture未来;
公开作废开始(){
future=scheduledThreadPool.schedule(logicalWorker,delay,TimeUnit.SECONDS);
}
公共停车场(){
如果(future!=null)future.cancel();
}
[/编辑]


此处有更多详细信息->

但在未来对象中的可调用对象中有一个runnable没有意义?它不是
runnable
callable
中,它是其中一个;对于您的示例,我认为您可以在
ScheduledExecutorService.schedule()
中使用,该函数的返回值将是一个
ScheduledFuture
,您可以在该函数上调用
cancel()
。文档中有一个很好的工作流示例。但在运行之前无法取消此线程。。。无论如何,它对我不起作用。你不需要显式地终止线程,SF可以为你处理。查看上一次编辑中的示例,或者通读几篇教程,谷歌有很多。使用
ThreadPoolExecutor
来完成这样一个简单的任务对我来说似乎有点过头了。尤其是它是为每个计时器对象创建的。@Dariusz不仅仅在您看来是如此,它是相当浪费的。但这意味着资源不是问题。