3

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

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

ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
    new ScheduledThreadPoolExecutor(corePoolSize)

...或者...

ScheduledExecutorService scheduledExecutorService =
    Executors.newSingleThreadScheduledExecutor();

...或者...

ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(corePoolSize);

我倾向于最后一个,但想知道一个明智的 corePoolSize 会是什么——也许是 1 以保持简单?

编辑: 最后我发现使用 top 方法最有好处(即直接实例化ScheduledThreadPoolExecutor)。ThreadPoolExecutor提供getActiveCount()用于获取活动线程的数量。这使我能够实现一个pause()等待暂停实际生效的方法 - 请参阅讨论

下一个决定是跟注scheduleAtFixedRate还是scheduleWithFixedDelay。我倾向于,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 实例上调用两次?

4

2 回答 2

4

正如其他人评论的那样,您需要更改的只是 Thread to 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。

每次执行都会实例化这个类的一个新实例吗?

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

否则它肯定不会工作 run() 肯定不能在同一个 Thread 实例上调用两次?

它可以工作,因为在您的代码中使用 Thread 令人困惑,因为您创建的线程没有被使用。它只是需要Runnable

于 2012-12-18T15:33:31.857 回答
2

单线程方法可以使用这样的Poller实现:

public class Poller implements Runnable {
    public void run() {
        while ( mayContinue ) {
            poll();
            Thread.sleep(5000);
        }
    }
}
于 2012-12-18T15:39:19.460 回答