【问题标题】:java- Calling a function at every intervaljava-每隔一段时间调用一个函数
【发布时间】:2019-04-29 23:17:16
【问题描述】:

我有一个程序,我可以在其中插入文件路径及其对应的参数到表。

在那之后,我还有另一个函数叫做do_Scan() 它扫描表并对其进行一些处理和索引。

但是,我希望这个函数do_Scan() 以一定的时间间隔运行,比如说每 N 分钟然后它会调用这个函数。 N 绝对是可配置的。

我正在考虑使用计时器类,但不太确定如何实现配置。我的想法是创建一个 Timer 函数,该函数将调用 do_Scan 方法。

类应该是这样的:

public void schedule(TimerTask task,long delay,long period){

}

我的主要方法:

public static void main(String[] args) throws Exception {

    Indexing test= new Indexing();
    java.sql.Timestamp date = new java.sql.Timestamp(new java.util.Date().getTime());
    // Exception e=e.printStackTrace();
    Scanner scanner = new Scanner(System.in);
    System.out.print("Enter a file path: ");
    System.out.flush();
    String filename = scanner.nextLine();
    File file = new File(filename);
    if(file.exists() && !file.isDirectory()) {
        test.index_request(filename,"Active",date,date,"");
    }else{
        test.index_request(filename,"Error",date,date,"Some errorCode");
    }

    // Call schedule() function 
}}

如何设置 Timer 类,使其在特定时间间隔内无限期运行?

【问题讨论】:

  • 例子?但我希望定时器在它自己的功能中
  • stackoverflow.com/questions/11416242/… 看看这对你有没有帮助
  • 是的,它确实有帮助。这是最好的方法吗?
  • 建议Runnable 的答案已经很老了。改用 lambdas(从 java 1.8 开始)。

标签: java


【解决方案1】:

为此,我建议您使用 Java 的 ScheduledExecutorService,它为您提供了一个 API 来以固定速率安排任务(以及其他 API)。

您有两种选择:

  1. 在您的任务中实现RunnableCallable(或类似的)并调用schedule() 方法:

    public class IndexingTask implements Runnable {
    
        @Override
        public void run() {
            schedule();
        }
    
        private void schedule() {
            //do something
        }
    }
    
    
    
    public static void main(String[] args) {
        //do some stuff
        long delay = getDelay();
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
        scheduledThreadPool.scheduleAtFixedRate(new IndexingTask(), 0, delay, TimeUnit.SECONDS);
    }
    
  2. 使用 Lambda 表达式内联:

    public static void main(String[] args) {
        //do some stuff
        long delay = getDelay();
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
        scheduledThreadPool.scheduleAtFixedRate(() -> doSomething(), 0, delay, TimeUnit.SECONDS);
    }
    

如果您使用的是 Spring Framework,您可以简单地使用 @Scheduled 注释,如下所示:

@Scheduled(fixedRate = 5000)
public void schedule() {
    //do something
}

【讨论】:

    【解决方案2】:

    有很多方法可以解决这个问题。我认为最简单的方法是,当你只在给定的地方使用这种方法而不使用像 Spring 这样的外部框架时:

    private void runWithInterval(long millis) {
        Runnable task = () -> {
            try {
                while (true) {
                    Thread.sleep(millis);
                    // payload
                }
            } catch(InterruptedException e) {
            }
        };
    
        Thread thread = new Thread(task);
        thread.setDaemon(true);
        thread.start();
    }
    

    每隔 1 分钟调用一次:

    runWithInterval(TimeUnit.MINUTES.toMillis(1));

    附言

    您可以在此处的其他帖子中看到其他详细信息:

    • 使用Spring时的@Scheduler注解
    • 使用单线程的线程池:ScheduledExecutorService scheduledThreadPool = Executors.newFixedThreadPool(1)
    • 使用Timer:new Timer().schedule(new Runnable() {}, TimeUnit.MINUTES.toMillis(1))

    【讨论】:

    • 这种方法会导致漂移,因为有效载荷会影响时序。
    【解决方案3】:

    最简单的方法是使用作为标准库一部分的类。

    java.util.Timer
    

    这是一个简单的使用例子:

    import java.util.Timer; 
    import java.util.TimerTask; 
    
    class MyTask extends TimerTask 
    { 
       public static int i = 0; 
       public void run() 
       { 
          System.out.println("Hello, I'm timer, running iteration: " + ++i); 
       } 
    } 
    
    public class Test 
    { 
       public static void main(String[] args) 
       { 
    
          Timer timer = new Timer(); 
          TimerTask task = new MyTask(); 
    
          timer.schedule(task, 2000, 5000);  // 2000 - delay (can set to 0 for immediate execution), 5000 is a frequency.
    
       } 
    } 
    

    【讨论】:

    • 如果里面出现错误怎么办,那我需要写另外一个函数来处理。
    • 是的,当然,但这是您的自定义逻辑,取决于应用程序。 Timer 只提供定期运行某些东西的能力。它不会让你免于处理错误
    【解决方案4】:

    如果您熟悉ReactiveX,那么有一个名为RxJava 的java 库可以用作:

    Flowable.interval(1, TimeUnit.SECONDS) // Or any other desired interval
            .subscribe(iteration -> System.out.println("Hello, I'm timer, running iteration: " + iteration));
    

    但是你真的应该阅读更多关于这种方法和库的信息

    【讨论】:

      【解决方案5】:

      您可以使用ScheduledThreadPoolExecutor

      假设你有一个任务方法:

      public void task(String foo, Integer bar){
          // ...
      }
      

      Java 1.8 之前

      ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
      executor.scheduleAtFixedRate(new Runnable() {
          @Override
          public void run() {
              task(fooParam, barParam);  
          }
      }, 0, 60, TimeUnit.SECONDS);
      

      Java 1.8+

      ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
      executor.scheduleAtFixedRate(() -> task(fooParam, barParam), 0, 60, TimeUnit.SECONDS);
      

      【讨论】:

      • 为什么在 Java 1.8 之前的例子中选择 2 作为 Poolsize?
      猜你喜欢
      • 2019-02-16
      • 2021-08-07
      • 1970-01-01
      • 2011-04-24
      • 2017-11-12
      • 1970-01-01
      • 2019-10-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多