我正在考虑将java.util.concurrent
包用于简单的轮询类。我们对可用于实现此目的的类,接口和方法的范围感到有点困惑,因此需要一些指导。以下是我的想法:
要做的第一个决定是如何实例化用于管理计划的类。有几种可能的选择,例如:
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
new ScheduledThreadPoolExecutor(corePoolSize)
...或...
ScheduledExecutorService scheduledExecutorService =
Executors.newSingleThreadScheduledExecutor();
...或...
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(corePoolSize);
我倾向于最后一个,但想知道一个明智的corePoolSize是什么 - 也许是为了让事情变得简单?
编辑: 最后,我发现使用top方法的最大好处(即直接实例化ScheduledThreadPoolExecutor)。 ThreadPoolExecutor提供getActiveCount()
以获取活动线程数。这使我能够实施pause()
方法,等待暂停实际生效 - 请参阅discussion。
下一个决定是致电scheduleAtFixedRate
还是scheduleWithFixedDelay
。我倾向于scheduleWithFixedDelay()
,因为轮询规律并不是那么重要,我不喜欢在瓶颈之后快速连续发生多次民意调查的想法。
但问题是:使用单个类来启动轮询并表示线程是否可行/可取? E.g:
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()
参数:是否会为每次执行实例化此类的新实例?否则它肯定不会工作,因为无法在同一个Thread实例上调用run()两次?
答案 0 :(得分: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);
}
}
BTW:如果你有Java 5.0,run()
方法没有@Override
。对于Java 6+,您应该拥有@Override。
是否会为每次执行实例化此类的新实例?
使用new
运算符时会创建一个新实例。
否则肯定无法运行run()肯定无法在同一个Thread实例上调用两次?
它可以工作,因为在您的代码中使用Thread会让您感到困惑,因为您创建的线程未被使用。它只需要Runnable
。
答案 1 :(得分:2)
单线程方法可以使用Poller
实现,如下所示:
public class Poller implements Runnable {
public void run() {
while ( mayContinue ) {
poll();
Thread.sleep(5000);
}
}
}