有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java可以将“this”传递到ScheduledExecutorService。scheduleWithFixedDelay()?

我正在考虑将java.util.concurrent包用于一个简单的轮询类。我有点困惑于可用于执行此操作的类、接口和方法的范围,因此希望您提供一些指导。以下是我迄今为止的想法:

要做的第一个决定是如何实例化用于管理计划的类。有几种可能的选择,例如:

ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
    new ScheduledThreadPoolExecutor(corePoolSize)

。。。或者

ScheduledExecutorService scheduledExecutorService =
    Executors.newSingleThreadScheduledExecutor();

。。。或者

ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(corePoolSize);

我倾向于最后一个,但想知道一个合理的核心池大小是多少——也许是为了保持简单

编辑:最后,我发现使用top方法(即直接实例化ScheduledThreadPoolExecutor)最有好处ThreadPoolExecutor提供^{}来获取活动线程的数量。这使我能够实现一个pause()方法,等待暂停实际生效——请参见discussion

下一个决定是调用^{}还是^{}。我倾向于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()不能在同一个线程实例上被调用两次


共 (1) 个答案

  1. # 1 楼答案

    正如其他人所评论的,您只需要将线程更改为可运行。您可能需要添加一些安全防护,这样就不会运行多个任务

    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?

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