java 当一个方法被连续调用时如何异步延迟?

sg24os4d  于 2023-01-07  发布在  Java
关注(0)|答案(4)|浏览(270)

我希望在调用printFirst()方法之前有1分钟的延迟,而不影响主线程。

代码

我试过了

// define delaying print-method using Timer
static void printFirst() {
  new java.util.Timer().schedule(
    new java.util.TimerTask() {
      public void run() {
        System.out.println(ts() + " First");
      }
    },60000
  );
}

// main to run
System.out.println(ts() + " Zero");
printFirst();
printFirst();
printFirst();
System.out.println(ts() + " Second");
System.out.println(ts() + " Third");
System.out.println(ts() + " Fourth");

实际输出

但结果是

Timestamp: 2023-01-05 17:40:43.664 Zero
Timestamp: 2023-01-05 17:40:43.666 Second
Timestamp: 2023-01-05 17:40:43.667 Third
Timestamp: 2023-01-05 17:40:43.667 Fourth
Timestamp: 2023-01-05 17:41:13.681 First
Timestamp: 2023-01-05 17:41:13.681 First
Timestamp: 2023-01-05 17:41:13.681 First

预期

我原以为以"第一"结尾的3行之间会有1分钟的间隔。

Timestamp: 2023-01-05 17:40:43.664 Zero
Timestamp: 2023-01-05 17:40:43.666 Second
Timestamp: 2023-01-05 17:40:43.667 Third
Timestamp: 2023-01-05 17:40:43.667 Fourth
Timestamp: 2023-01-05 17:41:43.667 First
Timestamp: 2023-01-05 17:42:43.667 First
Timestamp: 2023-01-05 17:43:43.667 First
eqoofvh9

eqoofvh91#

我们可以通过使用ExecutorService类和newSingleThreadExecutor()方法来实现预期的结果。

static ExecutorService es = Executors.newSingleThreadExecutor();

static void printFirst() {
    es.submit(() -> {
        try {
            TimeUnit.MILLISECONDS.sleep(60000);
            System.out.println(ts() + " First");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

主要方法仍然相同。

System.out.println(ts() + " Zero");
printFirst();
printFirst();
printFirst();
System.out.println(ts() + " Second");
System.out.println(ts() + " Third");
System.out.println(ts() + " Fourth");

运行时,结果为:

2023-01-06 00:05:45.72 Zero
2023-01-06 00:05:45.763 Second
2023-01-06 00:05:45.763 Third
2023-01-06 00:05:45.763 Fourth
2023-01-06 00:06:45.776 First
2023-01-06 00:07:45.782 First
2023-01-06 00:08:45.784 First
dgenwo3n

dgenwo3n2#

作为一个选项,您可以设置定时器以定期执行并限制运行次数

static void printFirst(long delay, int numberOfIterations) {
    new java.util.Timer().schedule(
        new java.util.TimerTask() {
            private int counter = 0;
            public void run() {
                System.out.println(ts() + " First");

                if(++counter == numberOfIterations) {
                    this.cancel();
                }
            }
        }, delay, delay
    );
}

然后使用一个命令printFirst(60000, 3);运行它

7bsow1i6

7bsow1i63#

问题

您的Timer.schedule(TimerTask task, long initialDelay)中的延迟仅为初始延迟,即计划任务和任务开始之间的时间。请参见文档中的参数:
delay-执行任务之前的延迟(毫秒)。

溶液

对于您的意图-如interval-您需要重载的姊妹方法schedule(TimerTask task, long delay, long period)将1分钟间隔作为第三个参数传递给名为period的参数:
安排指定任务在指定的延迟后开始重复执行,并保持固定延迟。后续执行大约以**固定间隔进行,间隔由指定的period**分隔。

import java.util.Timer;
import java.util.TimerTask;

// define the task, here in a method on demand
public static TimerTask createPrintTask(String text) {
   return new TimerTask() {
      public void run() {
        System.out.println(ts() + text);  // not sure how ts() is defined
      }
    };
}

// define print-method using Timer with interval and zero delay
static void printScheduledWithInterval(String text, int intervalMillis) {
  var initialDelayMillis = 0; // start immediately (first after 0 seconds)
  new Timer().schedule(createPrintTask(text), initialDelayMillis, intervalMillis);
}

// MAIN
System.out.println(ts() + " Zero");

// use to start the task asynchronously (it will continue to print every interval until canceled)
printScheduledWithInterval(" First", 60_000);  // 1 minute interval

System.out.println(ts() + " Second");
System.out.println(ts() + " Third");
System.out.println(ts() + " Fourth");

注意:在你的代码中,printFirst被调用了3次。大概是为了启动3个不同的任务或者打印3行。

任务调度何时结束?

这里的printScheduledWithInterval更确切地说是指调度一个打印作业以固定的时间间隔重复执行。
由于没有打印行数或最大执行计数的要求,定时器将不断启动新任务。

6uxekuva

6uxekuva4#

调用函数时,可以将秒数设置为参数

System.out.println(ts() + " Zero");
printFirst(60000);
printFirst(12000);
printFirst(18000);
System.out.println(ts() + " Second");
System.out.println(ts() + " Third");
System.out.println(ts() + " Fourth");

在你的工作中,

static void printFirst(long time) {
  new java.util.Timer().schedule(
    new java.util.TimerTask() {
      public void run() {
        System.out.println(ts() + " First");
      }
    },time
  );
}

相关问题