【问题标题】:Schedule multiple tasks on multiple threads在多个线程上安排多个任务
【发布时间】:2013-12-28 08:05:52
【问题描述】:

我需要定期执行一些数据收集,为此我想创建一个从不同服务器请求一些数据的任务。一些服务器将比其他服务器花费更多时间来处理请求并返回响应。

这就是为什么我想为每个服务器创建一个任务并异步执行任务。如果我以下列方式使用ScheduledExecutorService,每个任务将在其自己的线程中执行,还是所有任务将在同一个线程中执行?

如果一个任务抛出异常,所有其他计划任务都会失败,会发生什么情况?

this.scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r, "collectionThread");
                }
            });

for (String url:urls){
    this.scheduler.scheduleWithFixedDelay(new CollectorTask(url),
                                                  startupDelaySeconds,
                                                  scheduleRateSeconds,
                                                  TimeUnit.SECONDS);
}

【问题讨论】:

    标签: java multithreading scheduler


    【解决方案1】:

    您使用的是单线程执行器服务,因此所有任务都按顺序执行。如果其中任何一个引发异常,则所有下一个任务执行都将被取消。

    你可以使用

    Executors.newScheduledThreadPool(4)  // 4 is the max number of parallel jobs
    

    ...允许并行执行并将提交的作业的主体包装到

    try {
        ...
    } catch(Exception e){
        logger.warn("exception during task execution", e);
    }
    

    记录错误而不传播它们。

    可能会有轻微的延迟(几毫秒),具体取决于操作系统,任务永远不会早于预定时间执行。任务的执行可能会因之前的长时间运行或缺少空闲线程而延迟,但以下执行将按原计划运行:initialDelay + n * period

    【讨论】:

    • 那么,是否有一种方法可以异步执行任务并防止在任务失败后取消任务?
    • If any of them throws an exception, all next tasks executions are cancelled.我不这么认为,当前的executor线程会终止,但是executor会创建一个新的。
    • @AndreyChaschev 如果有超过 4 个任务会发生什么?任务是否会等待所有 4 个线程完成并开始执行另外 4 个任务,或者每当 4 个任务之一完成时,另一个任务将启动(总是有 4 个任务在运行,直到它们全部完成)?
    • @Katona,这是 afaik 的行为,我正在尝试为它查找 JavaDoc。
    • 那你需要一个缓存线程池。您可以将所有作业转发给Executors.newCachedThreadPool() 或破解ScheduledThreadPoolExecutor 以调用将keepAliveTime 设置为即60 秒的超级构造函数。我能想到的最简单的方法之一是将ScheduledThreadPoolExecutor 复制到您自己的版本中并更改此参数,该参数设置为0,并且在原始版本中不可配置。
    【解决方案2】:

    是的,你要做的是创建两个线程执行器。第一个是一个预定的执行器,它需要一个可运行的,用于启动您的实际可运行。所有这些可运行文件都会创建一个可运行的任务实例并将其提交给真正的执行者。该执行程序应该只是一个处理任务的普通线程池。

    private final ScheduledExecutorService scheduledExecutor = Executors
                .newSingleThreadScheduledExecutor();
    private final ExecutorService executor = Executors.newCachedThreadPool();
    
        private class SubmitTaskRunnable implements Runnable {
    
            @Override
            public void run() {
                executor.execute(new TaskRunnable());
            }
    
        }
    

    在您计划的执行程序上安排 SubmitTaskRunnable,因为该执行程序不会引发任何异常。让您的实际任务在缓存的执行器中运行将允许多个任务同时运行,即使之前的任务尚未完成。

    【讨论】:

      猜你喜欢
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多