Java Can';这';是否传递到ScheduleExecutorService.scheduleWithFixedDelay()中?

Java Can';这';是否传递到ScheduleExecutorService.scheduleWithFixedDelay()中?,java,multithreading,concurrency,scheduled-tasks,polling,Java,Multithreading,Concurrency,Scheduled Tasks,Polling,我正在考虑将java.util.concurrent包用于一个简单的轮询类。我对可用于此操作的类、接口和方法的范围有点困惑,因此希望您提供一些指导。到目前为止,我的想法如下: 要做的第一个决定是如何实例化用于管理计划的类。有几种可能的选择,例如: ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(corePoolSize) ……或者 ScheduledExe

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

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

ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
    new ScheduledThreadPoolExecutor(corePoolSize)
……或者

ScheduledExecutorService scheduledExecutorService =
    Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(corePoolSize);
……或者

ScheduledExecutorService scheduledExecutorService =
    Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService scheduledExecutorService =
    Executors.newScheduledThreadPool(corePoolSize);
我倾向于最后一个,但想知道一个合理的corePoolSize应该是什么-也许是为了保持简单

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

下一个决定是打电话还是打电话。我倾向于
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更改为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()
方法没有
@覆盖
。对于Java6+,您应该具有@Override

是否会为每次执行实例化此类的新实例

使用
new
操作符时,将创建一个新实例

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


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

单线程方法可以使用
轮询器
实现,如下所示:

public class Poller implements Runnable {
    public void run() {
        while ( mayContinue ) {
            poll();
            Thread.sleep(5000);
        }
    }
}

轮询器
不应扩展
线程
,而应只实现
可运行
!-不会创建传递的
Runnable
的新实例。
run()
方法只是被多次调用。我们不会将
Thread
提交给
ExecutorService
Executors
的全部目的是提供一个线程池来同时执行任务。如您的示例所示,如果您只希望一个线程定期执行一些轮询,您通常会自己启动/管理该线程,如
thread myThread=new thread(myPoller);myThread.start()。这些都是很好的注释,而且已经更有意义了。我习惯于扩展线程而不是实现Runnable,因为这通常是推荐的方法。因此,如果我改用Runnable,那么似乎每次执行都会重用同一个实例?希望Oracle文档中提到这一点!想象一下,如果不是这样的话。
ExecutorService
如何为下一次执行创建对象的新实例这根本不可能。再次谢谢你,汉诺。这看起来简单多了——曾经考虑过做类似的事情,但后来采用了StackOverflow,并转向了
java.concurrency
——但考虑到它的规模相当小,这可能是过虑了。唯一的问题是,我正在与一个现有产品集成,对它如何使用线程知之甚少——因此,也许java.concurrency可以防止潜在的问题和未来的证明。。。我现在有点不知所措了
mayContinue
必须是易失性的,Thread.sleep抛出一个必须捕获的InterruptedException。那么您建议Peter使用哪种方法?我猜ScheduledExecutorService必须存在,因为它可以防止所有常见的线程问题……如果可以的话,
ExecutorService
s可以有效地并发执行多个(通常较短)任务。例如,一个
执行器可以使用一个线程来处理一个又一个任务的加载,而无需创建除第一个线程之外的另一个线程。
Executor
还可以使用多个线程池来处理其任务,再次重复使用线程,而不是一次又一次地创建新线程。
ScheduledExecutorService
基本上与附加选项相同,它可以自动延迟或重复给定的任务,而不是一次性处理它们。谢谢。这看起来像是很好的代码。希望有办法分享答案,因为你和汉诺都提供了宝贵的意见。如果是这样,我会把它交给代表性最少的人。;)