Java在启动的线程上运行更多代码

时间:2018-08-26 10:43:48

标签: java multithreading

我有一个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”功能仍在运行,则在调用处理程序函数时,新的处理程序运行将等待其完成,然后运行。 行为将像命令队列一样,尽管我希望我并不需要真正地实现队列,而只是在同一线程上“运行更多代码”,然后获得我正在寻找的行为。 那可能吗?如果不是最好的方法是什么?

2 个答案:

答案 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();
    }
}

```