Java:用于在繁忙窗口期间计算点击次数的计时器或 ScheduleExecutorService?

发布于 2025-01-06 01:08:40 字数 595 浏览 1 评论 0原文

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

这提出了两个要求:

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

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

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

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

对此有更好的解决方案吗?

My problem is: I have a class which accepts files in a directory. Whenever the first object arrives it starts some timer to perform a compress on all the files in a directory which arrive during the next 60 seconds.

This raises two requirements:

1) I need to be able to check if the "countdown" is already running when a new file arrives. I don't want file2 to arrive 15 seconds after file1, then they get compressed together 45 seconds later only to have a second scheduled task fire 15 seconds after the first completed (to an empty directory).

2) Smart batching / non-constant polling. For example, if file1 arrives at time=0 and file2 arrives at time=59s, they would be compressed together. However, if file3 doesn't arrive until time=89s, and file4 arrives at time=129s, I want to make sure the next "compress" operation is not happening at timer=120s, but rather at timer=149s (60 seconds after file3 arrived).

In other words: only one timer/countdown should ever be running. If it's the first file since a compression, it should trigger a new one, but otherwise it should just be ignored.

I'm looking into java.util.Timer and Java.util.concurent.ScheduledExecutorService as solutions, but both seem built for having multiple processes, which I am trying to avoid.

Is there any better solution for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

万劫不复 2025-01-13 01:08:40

下面是一个示例代码:

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()都是由同一个锁守护的,所以不可能出现新文件但倒计时线程没有启动.

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

Here is an example code:

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. When onNewFile() is called it tries to start a new countDownThread if it is not already running.

  2. This thread waits for 60 seconds and starts compression.

  3. The last step resetThread() is a bit tricky. If we simply call:

    countDownThread = null;
    

    the code would not be thread-safe. First of all change made to countDownThread might not be visible by other threads. Moreover if new file appears between compressDirectoryContents() and simple assignment, it would get lost. That's why all operations are synchronized using the same lock.

    Because both onNewFile() and resetThread() are guarded by the same lock, it is not possible that new file appears but the count-down thread is not started.

Note that you don't need any fancy Timers or ScheduleExecutorService - creating a single thread every minute isn't an overkill.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文