【问题标题】:Java: Timer or ScheduleExecutorService for counting hits during busy windows?Java:计时器或 ScheduleExecutorService 用于在繁忙的窗口期间计算命中?
【发布时间】:2012-02-15 14:42:35
【问题描述】:

我的问题是:我有一个接受目录中文件的类。每当第一个对象到达时,它就会启动一些计时器来对目录中在接下来的 60 秒内到达的所有文件执行压缩。

这提出了两个要求:

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

2) 智能批处理/非常量轮询。例如,如果 file1 在 time=0 到达,而 file2 在 time=59s 到达,它们将被一起压缩。但是,如果 file3 直到 time=89s 才到达,而 file4 在 time=129s 到达,我想确保下一个“压缩”操作不会发生在 timer=120s,而是发生在 timer=149s(60 秒后文件 3 到达)。

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

我正在研究 java.util.Timer 和 Java.util.concurent.ScheduledExecutorService 作为解决方案,但它们似乎都是为拥有多个进程而构建的,我试图避免这种情况。

有没有更好的解决方案?

【问题讨论】:

  • 您如何收到文件已“到达”的通知? “到达”是什么意思 - 这是否意味着该文件已被创建它的任何应用程序完全写入和关闭?
  • 我的班级被传递了一个文件,然后将其移动到正确的目录并在压缩前检查计时器/倒计时。

标签: java multithreading timer


【解决方案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() 和简单赋值之间,它会丢失。这就是为什么所有操作都是synchronized使用同一个锁。

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

请注意,您不需要任何花哨的 Timers 或 ScheduleExecutorService - 每分钟创建一个线程并不过分。

【讨论】:

  • 谢谢,这似乎会奏效(现在正在尝试实施)。跟进:如果满足文件计数,是否可以强制触发 CompressionTask 运行? (假设 10 个文件在 60 秒内到达,所以立即触发它并在第 11 个文件到达时在 60 秒重新启动计数器,不管它是否在第一个计数器结束之前?)
  • @myingling:是的,有多种方式,但我将把实现细节留给你:-)。我认为最简单但有点笨拙的方法是致电countDownThread.interrupt()。但它给解决方案增加了一些复杂性。也许Queue 会帮助你?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 2021-12-29
  • 2021-11-19
  • 1970-01-01
相关资源
最近更新 更多