【问题标题】:Java scheduleAtFixedRate + Thread.sleepJava scheduleAtFixedRate + Thread.sleep
【发布时间】:2020-05-14 16:45:59
【问题描述】:

我只是在探索 Java 中 ScheduledExecutorService 类的方法 scheduleAtFixedRate

这是我的可疑代码:


ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

  Runnable command = () -> {
    System.out.println("Yo");
    try {
      Thread.sleep(4000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  };

  scheduledExecutorService.scheduleAtFixedRate(command, 0, 1, TimeUnit.SECONDS);

我预计每 1 秒 scheduleExecutorService 将尝试从池中获取新线程并启动它。

API 说:“scheduledExecutorService 创建并执行一个周期性操作,该操作首先在给定的初始延迟后启用,然后在给定的时间段内启用。/(不重要的已删除)/ 如果执行此任务花费的时间比它的周期长,那么后续的执行可能会延迟开始,但不会同时执行。”

结果 - 每个新线程每 4 秒启动一次。

所以,问题:

  1. 有什么问题 - Thread.sleep() 是否会停止所有线程或此行为的细微差别 - “如果此任务的任何执行时间超过其周期,则后续执行可能会延迟开始,但不会同时执行“?

  2. 如果在这种情况下“不会同时执行”为真 - 如果每个线程都将在前一个线程执行后启动,为什么我们需要这个由多个线程组成的池?

  3. 是否有任何简单有效的 scheduleAtFixedRate 使用示例,其中一个线程启动而前一个线程仍在执行?

【问题讨论】:

  • 您的问题 1 不清楚。你在问什么?
  • 2.因为您可以在该执行程序中安排多个任务。另外,因为这就是这个特定时间表的定义方式。
  • @AnkurChrungoo,我的意思是“睡眠”方法中的问题,或者就像文档说线程不会并发?现在我得到了答案,谢谢

标签: java multithreading


【解决方案1】:
  1. 答案在您提供的报价中。 Executor 等待任务完成,然后再次启动此任务。它可以防止同时执行一个任务的多个实例——在大多数情况下,这种行为是必需的。在您的情况下,Executor 启动一个任务,然后等待 1 秒的延迟,然后再等待 3 秒,直到当前任务完成,然后才再次启动此任务(它不一定启动新线程,它可能在同一个线程中启动任务)。

  2. 您的代码根本不使用线程池 - 您可以使用单线程执行器获得完全相同的结果。

  3. 如果你想获得这种行为:

    我预计每 1 秒 scheduleExecutorService 将尝试占用新线程 从池中启动它。

    那么你可以这样写:

    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
    
    Runnable command = () -> {
        System.out.println("Yo");
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    };
    
    Runnable commandRunner = () -> {
        scheduledExecutorService.schedule(command, 0, TimeUnit.SECONDS);
    }
    
    scheduledExecutorService.scheduleAtFixedRate(commandRunner, 0, 1, TimeUnit.SECONDS);
    

    (最好创建一个运行commandRunner的单线程ScheduledExecutorService并创建一个基于ExecutorService的线程池供commandRunner执行command使用)

【讨论】:

    【解决方案2】:

    有什么问题 - Thread.sleep() 是否停止所有线程或细微差别 这种行为 - “如果这个任务的任何执行时间比它的 期间,那么后续的执行可能会延迟开始,但不会 并发执行”?

    • 我不太明白你在这里的意思。但是,从本质上讲,在您共享的代码中, Thread.sleep() 只是使线程执行需要 4 秒,这比设置的 1 秒要长。因此,后续线程不会在 1 秒后执行,而只会在前一个线程执行约 4 秒后执行。

    如果在这种情况下“不会同时执行”是真的 - 为什么要这样做 如果每个线程都将在之后启动,我们需要这个由多个线程组成的池 执行前一个线程?

    • 您可能希望在同一个执行程序中安排一些其他类型的线程(执行不同的工作),这些线程可能与您共享的代码并行运行。不过,您当前的代码只需要池中的 1 个线程,因为您只安排一个作业(可运行)。

    有没有使用 scheduleAtFixedRate 的简单有效示例, 一个线程从哪里开始,而前一个线程仍在执行?

    • 如文档中所述,您以固定速率(使用当前代码)安排的作业不会发生并发执行

    【讨论】:

      【解决方案3】:
      public class Poll {
        ScheduledFuture<?> future;
        static int INIT_DELAY = 1;
        static int REPEAT_PERIOD = 2;
        static int MAX_TRIES = 3;
        int tries = 1;
        
        
        Runnable task = () -> {
          System.out.print( tries + ": " + Thread.currentThread().getName() + " " );
          
          if ( ++tries > MAX_TRIES ) {
            future.cancel( false );
          }
        };
        
        
        void poll() {
          ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
          future = executor.scheduleAtFixedRate( task, INIT_DELAY, REPEAT_PERIOD, TimeUnit.SECONDS );
          
          System.out.println( "Start: " + tries + ": " + Thread.currentThread().getName() + " " );
        
          try {
            future.get();
            
          } catch ( InterruptedException | ExecutionException e ) {
            System.out.println( e.getMessage() );
            
          } catch ( CancellationException e ) {
            System.out.println( "Regular End Of Scheduled Task as Designed.");
            
          } finally {
            executor.shutdown();
            executor.shutdownNow();
          }
          
          System.out.println( "Return The Result." );
        }
        
        
        // The Driver
        public static void main( String[] args ) {
          new Poll().poll();
        }
      }
      

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 2019-12-22
      • 2011-07-30
      • 2014-08-30
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      相关资源
      最近更新 更多