java - 可以将 'this' 传递给 ScheduledExecutorService.scheduleWithFixedDelay() 吗?

标签 java multithreading concurrency scheduled-tasks polling

我正在考虑将 java.util.concurrent 包用于一个简单的轮询类。我对可用于执行此操作的类、接口(interface)和方法的范围感到有点困惑,因此希望得到一些指导。到目前为止,这是我的想法:

首先要做的决定是如何实例化用于管理日程的类。有几个可能的选项,例如:

ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
    new ScheduledThreadPoolExecutor(corePoolSize)

……或者……

ScheduledExecutorService scheduledExecutorService =
    Executors.newSingleThreadScheduledExecutor();

……或者……

ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(corePoolSize);

我倾向于最后一个,但想知道合理的 corePoolSize 应该是多少 - 也许 1 是为了让事情变得简单?

编辑: 最后我发现使用 top 方法(即直接实例化 ScheduledThreadPoolExecutor )最有好处。 ThreadPoolExecutor提供 getActiveCount()用于获取 Activity 线程数。这允许我实现一个 pause() 方法,该方法等待暂停真正生效 - 参见 discussion .

下一个决定是是否调用scheduleAtFixedRatescheduleWithFixedDelay .我倾向于 scheduleWithFixedDelay(),因为轮询规律性并不是那么重要,而且我不喜欢在瓶颈后快速连续发生多个轮询的想法。

但这里有一个问题:使用一个既启动轮询又代表线程的类是否可行/可取?例如:

public class Poller extends Thread {
    @Override
    public void run() {
        ...
    }

    public void startPolling() {
        ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
        exec.scheduleWithFixedDelay(this, 0, 5000, TimeUnit.MILLISECONDS);
    }
}

这里我不确定的主要部分是第一个 scheduleWithFixedDelay() 参数:是否会为每次执行实例化此类的新实例?否则它肯定不会工作,因为 run() 不能在同一个 Thread 实例上调用两次?

最佳答案

正如其他人评论的那样,您只需将 Thread 更改为 Runnable。您可能想要添加一些安全防护,以便不会运行多个任务。

public class Poller implements Runnable {
    final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    Future future = null;

    @Override
    public void run() {
        ...
    }

    public void startPolling() {
        if (future != null && !future.isDone()) {
           future.cancel(true); // stop before restarting
           // or
           return; // already running
        }
        future = exec.scheduleWithFixedDelay(this, 0, 5000, TimeUnit.MILLISECONDS);
    }
}

顺便说一句:如果您使用的是 Java 5.0,则 run() 方法没有 @Override。对于 Java 6+,您应该有 @Override。

Will a new instance of this class be instantiated for each execution?

当您使用 new 运算符时,会创建一个新实例。

Otherwise it surely wouldn't work run() surely can't be called on the same Thread instance twice?

之所以可行,是因为在您的代码中使用 Thread 会造成混淆,因为您创建的线程未被使用。它只需要是 Runnable

关于java - 可以将 'this' 传递给 ScheduledExecutorService.scheduleWithFixedDelay() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13936082/

相关文章:

java - 线程运行方法内部使用的方法的同步

java - java中的 "simple"线程池

java - Debian/etc/init.d/script 没有运行?

java - 如何在 Java 中复制对象?

java - (JAVA) 如何在浏览器中打开临时 htm 文件?

java - 使用 GWT 时发生 Hibernate 异常

c# - 需要帮助使用线程来监视指定文件夹中的 txt 文件

javascript - 回调总是异步的吗?

java - 如何执行具有异步子任务的顺序任务

java - 如何并行调用 3 个 REST 端点?