2013-04-01 114 views
0

我在多线程中不是很好,这可能是一个基本问题。但我一直无法找到答案。增加睡眠/等待时间直到需要

场景: 比方说,我有一个事件监听器被某些东西触发。每次事件被解雇,我都想开始一个新的线程,需要大约3秒钟的时间来执行。

问题: 问题是该事件可以在一秒钟内多次触发,而且我不想一次启动多个线程。

要求: 我该如何安排一个线程让事件发生后1000毫秒。如果事件继续发射,我想继续延迟线程的预定时间。这样,我的线程在上次事件被触发1000毫秒后执行。

+0

你为什么在一个单独的线程中执行动作?为什么不在actionPerformed方法本身? –

+0

@VishalK如果每次发生事件,OP可能不想阻止EDT。 –

回答

2

我会使用一个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); 
    } 
} 

TaskRunnable,做您的长时间运行的操作。 Listener是您的听众类。

Listener.actionPerformed方法中,我们首先通过使用Future来检查是否已经安排了一个任务,如果我们取消它。我们不需要担心这里的种族危害,如果任务在isDone的电话和cancel的电话之间完成,则不会发生任何事情。

如果任务是在点运行时,Listener火灾则该任务将完成,因为cancel方法被调用false。另一个任务将计划在侦听器触发后运行一秒,或者当前运行的任务完成后(因为我们只使用一个线程,只有一个任务可以运行)。

Listener然后将安排任务的新执行在一秒钟内完成。

3

事件监听器在启动时创建并启动一个新的专用线程。线程包含要执行的任务列表,并按顺序逐个执行它们。每当偶数侦听器收到一个新事件时,它就会创建一个新任务,并将其添加到专用线程中的任务列表中。

编辑:尤金建议使用线程池,这可能会对您的情况有好处,如果您需要花费大量时间处理每项任务的大量工作。看看Java API中的线程池,像这样:http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

+0

如果有1000个任务会怎么样?我认为线程池会好很多 – Eugene

+1

@Eugene,这是一个公平的变化。我认为OP是计时任务执行(3秒),包括线程的创建,这可能占用了90%的时间,所以我不认为池是必要的,但我会添加它。 – jn1kk