2012-02-15 69 views
2

我的问题是:我有一个类接受目录中的文件。每当第一个对象到达时,它启动一些定时器对目录中的所有文件执行压缩,这些文件在接下来的60秒内到达。Java:计时器或ScheduleExecutorService用于计算繁忙窗口中的点击次数?

这就提出了两个要求:

1)我需要能够检查是否在新文件到达“倒计时”已经在运行。我不希望file2在file1之后15秒到达,然后它们在45秒后被压缩在一起,只有在第一次完成(到一个空目录)15秒后触发第二个计划任务。

2)智能配料/非恒定轮询。例如,如果file1在时间= 0到达,file2在时间= 59s到达,它们将被压缩在一起。但是,如果file3在时间= 89s之前没有到达,并且file4在时间= 129s到达,我想确保下一个“压缩”操作不在定时器= 120s发生,而是在定时器= 149s(60秒之后file3抵达)。

换句话说:只有一个定时器/倒计时应该运行。如果它是自压缩以来的第一个文件,它应该触发一个新的文件,否则它应该被忽略。

我正在研究java.util.Timer和Java.util.concurent.ScheduledExecutorService作为解决方案,但都似乎建立了多个进程,我试图避免。

有没有更好的解决方案呢?

+0

您如何收到文件已经“抵达”的通知? “到达”意味着什么 - 这是否意味着该文件已被完全编写并由任何应用程序创建它关闭? – 2012-02-15 14:55:03

+0

我的课程是通过一个文件,然后将其移动到适当的目录并在压缩之前检查定时器/倒计时。 – Bing 2012-02-15 15:04:04

回答

1

下面是一个例子代码:

private Thread countDownThread; 

public synchronized void onNewFile() { 
    startCountDownThreadIfNotYetRunning(); 
} 

public synchronized void resetThread() { 
    if(uncompressedFilesExist()) { 
     startCountDownThreadIfNotYetRunning(); 
    } 
} 

public synchronized void startCountDownThreadIfNotYetRunning() { 
    if(countDownThread == null) { 
     new Thread(new CompressionTask()).start(); 
    } 
} 

private class CompressionTask implements Runnable { 
    @Override 
    public void run() { 
     try { 
      Thread.sleep(60 * DateUtils.MILLIS_PER_SECOND); 
      compressDirectoryContents(); 
      resetThread(); 
     } 
     catch (InterruptedException e) { } 
    } 
} 
  1. onNewFile()被调用它试图启动一个新的countDownThread,如果它尚未运行。

  2. 此线程等待60秒并开始压缩。

  3. 最后一步resetThread()有点棘手。如果我们只是打电话:

    countDownThread = null; 
    

    该代码不会线程安全。首先对countDownThread所做的更改可能不会被其他线程看到。此外,如果在compressDirectoryContents()和简单分配之间出现新文件,它将会丢失。这就是为什么所有操作都是​​使用相同的锁。

    因为onNewFile()resetThread()都被相同的锁保护,所以不可能出现新文件,但是不启动倒计时线程。

注意,你不需要任何花哨Timer S或ScheduleExecutorService - 创建一个单独的线程分秒不矫枉过正。

+0

谢谢,这看起来好像会起作用(现在试图实现它)。后续:如果满足文件计数,是否可以强制触发CompressionTask运行? (说10个文件到达下60秒左右,所以当11日的文件到达时,不管它是第一个计数器将结束之前触发它的时候了,并重新启动在60秒计数器?) – Bing 2012-02-15 16:34:40

+0

@myingling:是的,在几个方面,但我会将实施细节留给你:-)。我认为最容易,但有点hacky的方式是调用'countDownThread.interrupt()'。但它增加了解决方案的一些复杂性。也许'Queue'会帮助你? – 2012-02-15 16:42:31