我有一个JavaFX应用程序,并且在其中捕获键盘事件并发送给处理程序函数,GUI部分与该问题无关,因此此处未显示。 我的问题只是Java中的一个线程问题。 这是当前的处理函数:
@Override
public void handle(KeyEvent event) {
log.debug("handle getCode: {}", event.getCode());
Thread thread = new Thread(() -> {
switch (event.getCode()) {
case NUMPAD0:
sendCommand(HELLO);
break;
case NUMPAD1:
sendCommand(TIME);
break;
case NUMPAD2:
sendCommand(START_TOUR);
break;
case DIGIT1:
sendCommand(JOKE);
break;
}
});
thread.setDaemon(true);
thread.start();
}
我要实现的是,如果以前的“ sendCommand”功能仍在运行,则在调用处理程序函数时,新的处理程序运行将等待其完成,然后运行。 行为将像命令队列一样,尽管我希望我并不需要真正地实现队列,而只是在同一线程上“运行更多代码”,然后获得我正在寻找的行为。 那可能吗?如果不是最好的方法是什么?
答案 0 :(得分:1)
您可以使用ExecutorService
with a single thread,它将为您处理。如果上一个任务仍在运行,则该任务将被放入队列。
Executor executor = Executors.newSingleThreadExecutor();
@Override
public void handle(KeyEvent event) {
log.debug("handle getCode: {}", event.getCode());
executor.execute(() -> {
switch (event.getCode()) {
case NUMPAD0:
sendCommand(HELLO);
break;
case NUMPAD1:
sendCommand(TIME);
break;
case NUMPAD2:
sendCommand(START_TOUR);
break;
case DIGIT1:
sendCommand(JOKE);
break;
}
});
}
答案 1 :(得分:0)
您可以使用Strand
(附加信息here。它是Executor
的包装,以确保一次通过它提交的任务(链)仅在运行。 / p>
示例实现:
```java 公共类Strand实施执行程序{ //此队列可以扩展为吞下重复事件 私有最终队列队列= new ConcurrentLinkedQueue <>();
private final AtomicBoolean scheduled = new AtomicBoolean(false);
private final Executor delegate;
private final Runnable THE_TASK = () -> {
scheduled.set(false);
final Runnable task = queue.poll();
if (task != null) {
try {
task.run();
} catch (Throwable th) {
; // do something meaningful here, e.g. redispatch to some exception handler
} finally {
schedule();
}
}
};
public Strand(Executor delegate) {
this.delegate = delegate;
}
private void schedule() {
final boolean needToSchedule;
synchronized (this) {
needToSchedule = ! queue.isEmpty() && scheduled.compareAndSet(false, true);
}
if (needToSchedule) {
try {
delegate.execute(THE_TASK);
} catch (RuntimeException ex) { // failed to schedule with the delegate
scheduled.set(false);
}
}
}
@Override
public void execute(Runnable task) {
queue.add(task);
schedule();
}
}
```