我在多线程方面不是很好,这可能是一个基本问题。但我一直无法找到答案。
场景: 假设我有一个被某些东西触发的事件监听器。每次触发事件时,我都想启动一个大约需要 3 秒才能执行的新线程。
问题: 问题是事件可以在一秒钟内多次触发,我不想一次启动多个线程。
要求: 我如何安排一个线程让我们说在事件发生后 1000 毫秒。如果事件继续触发,我想继续延迟线程的预定时间。这样我的线程在最后一次触发事件的 1000 毫秒后执行。
我在多线程方面不是很好,这可能是一个基本问题。但我一直无法找到答案。
场景: 假设我有一个被某些东西触发的事件监听器。每次触发事件时,我都想启动一个大约需要 3 秒才能执行的新线程。
问题: 问题是事件可以在一秒钟内多次触发,我不想一次启动多个线程。
要求: 我如何安排一个线程让我们说在事件发生后 1000 毫秒。如果事件继续触发,我想继续延迟线程的预定时间。这样我的线程在最后一次触发事件的 1000 毫秒后执行。
事件侦听器在启动时创建并启动一个新的私有线程。该线程包含要执行的任务列表,并按顺序一次执行一个任务。每次偶数侦听器接收到一个新事件时,它都会创建一个新任务,并将其添加到私有线程中的任务列表中。
编辑:Eugene 建议使用线程池,如果您有大量工作要做,每项任务占用大量时间,这对您来说可能是有益的。看看 Java API 中的线程池,如下所示:http ://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
我会使用ScheduledExecutorService
- 安排任务在一秒钟内发生,如果已经安排了一项任务,请取消它并安排一个新的任务在一秒钟内发生
这样,您的任务将在最后一次触发事件后一秒钟执行。
private class Task implements Runnable {
@Override
public void run() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private Future<?> scheduledTaskHandle;
private class Listener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (scheduledTaskHandle != null && !scheduledTaskHandle.isDone()) {
scheduledTaskHandle.cancel(false);
}
scheduledTaskHandle = executorService.schedule(new Task(), 1, TimeUnit.SECONDS);
}
}
这Task
是一个Runnable
可以进行长时间运行的操作。这Listener
是你的听众课。
在该Listener.actionPerformed
方法中,我们首先使用 来检查一个任务是否已经被调度Future
,如果是我们就取消它。我们不需要担心竞争风险,如果任务在调用isDone
和调用之间完成,cancel
那么什么都不会发生。
如果任务在Listener
触发时正在运行,则该任务将完成,因为该cancel
方法是用 调用的false
。另一个任务将被安排在侦听器触发后一秒或当前正在运行的任务完成后运行(因为我们只使用一个线程,不能运行多个任务)。
然后Listener
将安排任务的新执行在一秒钟内发生。