如何使用ScheduledExecutorService实现固定速率轮询器?

时间:2013-03-15 10:06:36

标签: java multithreading scheduled-tasks runnable scheduledexecutorservice

鉴于以下课程:

public class Poller implements Runnable {
    public static final int CORE_POOL_SIZE = 4;

    public boolean running;
    public ScheduledExecutorService ses;

    public void startPolling() {
        this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
        this.ses.scheduleAtFixedRate(this, 0, 1, TimeUnit.SECONDS);
    }

    public void run() {
        running = true;
        // ... Do something ...
        running = false;
    }
}

ScheduledExecutorService的核心线程池大小为4,但是会创建多个轮询器线程吗?由于this被传递到scheduleAtFixedRate,这意味着只会有一个线程 - 或者在幕后发生更复杂的事情吗?

还有2个红利问题: -

  1. running应该static吗?
  2. CORE_POOL_SIZE是多余的吗?

3 个答案:

答案 0 :(得分:4)

  

ScheduledExecutorService的核心线程池大小为4但是是否会创建多个轮询器线程?

这取决于 - 如果你运行你的程序足够长,它可能会创建4个线程。如果在仅运行一次或两次计划任务后退出,则可能只会看到2个或3个线程。

为什么重要?

监控线程创建的一种方法是提供您自己的ThreadFactory

this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE, new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                System.out.println("Creating thread");
                return new Thread(r);
            }
        }); 
  

运行应该是静态的吗?

这取决于你想要实现的目标...因为你不是真的在你的例子中使用它很难说。如果您有多个Poller实例并且希望它们不能同时运行,则可能需要将其设置为静态。

无论是否为静态,如果您将其用作旗帜,您应该使其变得不稳定以确保可见性。

  

CORE_POOL_SIZE是多余的吗?

不确定你的意思。这是一个必需参数,因此您需要提供一个值。如果你确定不会同时运行两个执行,那么你只能有一个线程。这也将阻止并发执行(因此,如果一个计划任务需要启动但另一个已经运行,则新计划任务将被延迟)。

答案 1 :(得分:3)

scheduleAtFixedRate(Runnable,long initialDelay,long period,TimeUnit timeunit)

此方法安排定期执行的任务。该任务在initialDelay之后第一次执行,然后在每次期限到期时重复执行。

如果给定任务的任何执行引发异常,则不再执行该任务。如果没有抛出异常,则该任务将继续执行,直到ScheduledExecutorService关闭为止。

如果任务执行的时间比其计划执行之间的时间长,则下一次执行将在当前执行完成后开始。计划任务一次不会由多个线程执行。

答案 2 :(得分:1)

为什么要将执行者服务放在Runnable课程中? 您应该将ScheduledExecutorService分离为Singleton而不是runnable类的变量。

提醒这个ScheduledExecutorService是一个线程容器,所以当你编写这个

this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE);

当你输入这段代码时,它会根据大小的值创建很多线程

this.ses.scheduleAtFixedRate(this, 0, 1, TimeUnit.SECONDS);

ScheduledExecutorService将随机选择一个空闲的线程,每隔1秒运行一次该类,直到完成为止。如果将sleep放在run time方法中,该方法的长度超过了period time的值,则传递给预定的线程,它将不会创建另一个线程,直到第一个线程完成。因此,如果您希望多个线程同时运行此Poller,请创建多个Poller实例并将其传递给ScheduledExecutorService

CORE_POOL_SIZE对我来说这不是多余的,从配置文件中获取值是一个常量。

运行应该是静态的吗? 这取决于你需要什么。如果你打算创建Poller的多个实例,那么你不应该