非活动用户的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不仅仅在您看来是如此,它是相当浪费的。但这意味着资源不是问题。