Flux.interval 使用说明书

interval

public static Flux<Long> interval(Duration period)
Create a  Flux that emits long values starting with 0 and incrementing at specified time intervals on the global timer. The first element is emitted after an initial delay equal to the period. If demand is not produced in time, an onError will be signalled with an  overflow IllegalStateException detailing the tick that couldn't be emitted. In normal conditions, the  Flux will never complete.

创建一个 Flux,它会从 0 开始发出 long 类型的值,并按照指定的时间间隔递增,使用全局计时器。第一个元素会在与周期相等的初始延迟之后发出。如果没有及时产生需求,将触发 onError,并通过 IllegalStateException 抛出一个溢出错误,详细说明无法发出的计时值。在正常情况下,该 Flux 永远不会完成。

Runs on the  Schedulers.parallel() Scheduler.

该操作将在 Schedulers.parallel() 调度器上运行。

Parameters:

period - the period  Duration between each increment

Returns:

a new  Flux emitting increasing numbers at regular intervals

参数:

period - 每次递增之间的周期持续时间 Duration

返回值:

返回一个新的 Flux,它会在固定的时间间隔内发出递增的数字。

Flux.interval(Duration period) 是一个在 Reactor 库中常见的工具,用于创建一个持续发出数值的流。这个方法会按照指定的 Duration 时间间隔生成从 0 开始的 Long 序列,并不断递增。

以下是其基本的功能解释和用法:

1. 方法介绍

Flux.interval(Duration period) 方法会创建一个定时的 Flux,每隔给定的时间间隔发出一个递增的 Long 值。

2. 参数

  • period: 一个 Duration 对象,用于定义发射元素之间的时间间隔。

3. 返回值

  • 返回一个 Flux<Long>,其会每隔指定时间发射一个递增的 Long 值(从 0 开始)。

示例代码

java

import reactor.core.publisher.Flux;

import java.time.Duration;

public class IntervalExample {
    public static void main(String[] args) throws InterruptedException {
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(1));

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 为了能让程序持续运行,等待 10 秒
        Thread.sleep(10000);
    }
}

4. 特性

  • 每次发出的是 Long 类型的数据,从 0 开始递增。
  • 它是异步执行的,通常会在独立的线程中运行。
  • 可以与 take(n) 或者其他操作符结合使用来控制流的终止。

5. 注意事项

  • Flux.interval 会一直持续运行,直到你取消订阅或者通过操作符让其完成(如 take(n) 只取前 n 个)。
  • 它默认会在 Schedulers.parallel() 的线程池上执行,因此在控制线程时需要小心管理。

6. 结合操作符

通常 Flux.interval 可以与其他操作符结合,例如 map, filter, take 等等。

示例:取前 5 个数据并输出
java

import reactor.core.publisher.Flux;

import java.time.Duration;

public class IntervalExample {
    public static void main(String[] args) throws InterruptedException {
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(1))
                                      .take(5); // 只取前 5 个元素

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 等待足够的时间让 Flux 生成完数据
        Thread.sleep(6000);
    }
}

这个例子会输出从 0 到 4 的五个 Long 值,每个值间隔 1 秒,之后自动完成。

应用场景

  • 可以用于实现定时任务。
  • 在需要持续产生数据或事件的场景中,比如轮询某个 API、定时执行某个功能等。

这种定时触发的功能在开发中非常常见,也非常实用,尤其是在需要处理类似调度任务的场景时非常方便。

interval

public static Flux<Long> interval(Duration delay,
                                  Duration period)
Create a  Flux that emits long values starting with 0 and incrementing at specified time intervals, after an initial delay, on the global timer. If demand is not produced in time, an onError will be signalled with an  overflow IllegalStateException detailing the tick that couldn't be emitted. In normal conditions, the  Flux will never complete.

创建一个 Flux,从 0 开始发出 long 值,并按照指定的时间间隔递增,在全局定时器上经过初始延迟后开始。如果未及时产生需求,则会发出包含无法发出的 tick 详细信息的 overflow IllegalStateException 错误信号。在正常情况下,该 Flux 将永不完成。

Runs on the  Schedulers.parallel() Scheduler.

该操作在 Schedulers.parallel() 调度器上运行。

Parameters:

delay - the  Duration to wait before emitting 0l
period - the period  Duration before each following increment

Returns:

a new  Flux emitting increasing numbers at regular intervals

参数:

delay:在发出第一个 0 之前等待的持续时间 (Duration)。
period:每次递增之间的时间间隔 (Duration)。

返回值:

一个新的 Flux,按固定时间间隔发出递增的数字。

Flux.interval(Duration delay, Duration period) 是 Reactor 库中的一个方法,它允许创建一个带初始延迟的定时 Flux。

与只指定 period 的版本不同,这个方法不仅允许你设置每次事件之间的间隔时间,还允许你设置初始延迟时间。

1. 方法介绍

  • Flux.interval(Duration delay, Duration period) 会创建一个从 0 开始递增的 Flux<Long>,每隔 period 指定的时间间隔发出一次,并且在开始前会有一个 delay 的初始延迟。

2. 参数

  • delay: 表示在生成第一个元素之前的初始延迟时间。
  • period: 表示每次发出元素之间的时间间隔。

3. 返回值

  • 返回一个 Flux<Long>,其会在延迟 delay 时间后,从 0 开始发出递增的 Long 序列,发出每个元素之间的时间间隔是 period。

示例代码

java

import reactor.core.publisher.Flux;

import java.time.Duration;

public class IntervalWithDelayExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Flux,在 2 秒延迟后,每隔 1 秒发出一个递增的值
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(2), Duration.ofSeconds(1));

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 等待足够的时间让 Flux 生成数据
        Thread.sleep(10000);
    }
}

4. 特性

  • 初始的发射会延迟指定的 delay 时间。
  • 每个后续发射都会按照指定的 period 时间间隔来触发。
  • 从 0 开始,递增发射 Long 值。
  • 默认使用 Schedulers.parallel() 线程池。

5. 注意事项

  • 如果不需要初始延迟,应该使用 Flux.interval(Duration period) 。
  • 这个 Flux 会一直运行,直到手动取消订阅或者通过操作符(如 take(n))来控制终止。

6. 结合操作符

可以与 take 或其他操作符结合使用,来控制流的行为。

示例:取前 5 个值,初始延迟 3 秒
java

import reactor.core.publisher.Flux;

import java.time.Duration;

public class IntervalWithDelayExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Flux,延迟 3 秒后开始,每隔 1 秒发出一个值,只取前 5 个值
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(3), Duration.ofSeconds(1))
                                      .take(5); // 只取前 5 个值

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 等待足够的时间让 Flux 生成完数据
        Thread.sleep(10000);
    }
}

这个例子会在延迟 3 秒后,每隔 1 秒发出一个值,并最终输出 5 个值。

应用场景

  • 定时任务调度:带有初始延迟的任务调度非常常见,尤其是在系统初始化后需要一段准备时间的场景。
  • 周期性操作:比如在网络应用中,可能需要先等待一定时间,然后周期性地轮询某个服务。
  • 触发器控制:可以用来设置系统中定时任务的开始时间和执行频率。

Flux.interval(Duration delay, Duration period) 在处理需要延迟开始的周期性任务时非常有用。

interval

public static Flux<Long> interval(Duration period,
                                  Scheduler timer)
Create a  Flux that emits long values starting with 0 and incrementing at specified time intervals, on the specified  Scheduler. The first element is emitted after an initial delay equal to the period. If demand is not produced in time, an onError will be signalled with an  overflow IllegalStateException detailing the tick that couldn't be emitted. In normal conditions, the  Flux will never complete.

创建一个 Flux,按指定的时间间隔发出从 0 开始递增的 long 值,在指定的调度器上运行。第一个元素将在与周期相等的初始延迟后发出。如果未能按时产生需求,则会发出 onError,并带有 IllegalStateException 异常,详细说明无法发出的 tick。在正常情况下,Flux 将永不完成。

Parameters:

period - the period  Duration between each increment
timer - a time-capable  Scheduler instance to run on

Returns:

a new  Flux emitting increasing numbers at regular intervals

参数:

period - 每次递增之间的时间间隔 Duration。
timer - 一个支持时间操作的调度器 Scheduler 实例。

返回值:

一个新的 Flux,将按固定的时间间隔递增发出数字。

Flux.interval(Duration period, Scheduler timer) 是 Reactor 提供的一种定时器工具,它允许你创建一个 Flux<Long>,每隔给定的 Duration 时间间隔发出递增的 Long 值,并且可以指定一个自定义的调度器 Scheduler 来控制这些定时事件在哪个线程或线程池上执行。

1. 方法介绍

Flux.interval(Duration period, Scheduler timer) 可以按照指定的 period 时间间隔发射从 0 开始的 Long 序列,并且通过传递的 Scheduler 决定执行的线程。

2. 参数

  • period: 一个 Duration 对象,表示发射元素之间的时间间隔。
  • timer: 一个 Scheduler,用于调度定时器的执行。

3. 返回值

  • 返回一个 Flux<Long>,它在每隔指定的 period 时间发出一个递增的 Long 值,从 0 开始。

4. 示例代码

java

import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.time.Duration;

public class IntervalWithSchedulerExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Flux,每隔 1 秒发出一个值,在指定的 Scheduler 上运行
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(1), Schedulers.newSingle("custom-scheduler"));

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 为了演示,让主线程等待 5 秒
        Thread.sleep(5000);
    }
}

在这个例子中,Flux.interval(Duration.ofSeconds(1), Schedulers.newSingle("custom-scheduler")) 每隔 1 秒发射一次数据,且数据是在一个名为 custom-scheduler 的自定义线程上执行的。

5. Scheduler 的作用

Scheduler 决定了定时器在哪个线程上执行,可以使用不同的调度器类型来优化性能或控制线程资源:

  • Schedulers.parallel(): 在共享的并行线程池上执行。
  • Schedulers.single(): 在单线程调度器上执行。
  • Schedulers.elastic(): 使用弹性线程池,每个任务会使用不同的线程,如果线程空闲时间过长则会被回收。
  • Schedulers.boundedElastic(): 创建一个更具约束的弹性线程池,用于并发性较强但任务执行时间较长的场景。
  • Schedulers.immediate(): 立即在当前线程执行。
  • Schedulers.fromExecutorService(ExecutorService executor): 使用自定义的 ExecutorService 来作为调度器。

6. 注意事项

  • 使用 Scheduler 可以让你更加灵活地控制线程池和任务调度的策略,避免过度占用默认线程池的资源。
  • 如果你没有指定 Scheduler,则 Flux.interval 默认在 Schedulers.parallel() 上执行。

7. 结合操作符

与其他 Flux 类似,你可以使用 map, filter, take 等操作符来处理发出的数据。

示例:在自定义线程池上执行并只取前 5 个元素
java

import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.time.Duration;

public class IntervalWithSchedulerExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Flux,每隔 1 秒发出一个值,在自定义 Scheduler 上运行,并取前 5 个元素
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(1), Schedulers.newSingle("custom-scheduler"))
                                      .take(5); // 只取前 5 个值

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 等待足够的时间让 Flux 生成完数据
        Thread.sleep(6000);
    }
}

这个例子会在指定的 Scheduler 上执行,每隔 1 秒发出一个值,并且只会发出前 5 个值。

应用场景

  • 线程控制:当你需要控制定时任务在哪个线程池或线程上执行时,指定 Scheduler 非常有用。
  • 资源管理:对于高并发系统,可以使用 Schedulers.boundedElastic() 或者自定义线程池来更好地管理线程资源,避免系统默认线程池被占满。
  • 定时任务:在 Web 应用或者微服务中,某些任务可能需要定期执行,并且需要在特定的线程池上处理,比如进行某些后台的管理任务。

通过使用 Scheduler,可以让你的 Flux.interval 更加灵活,适用于更复杂的线程和任务调度场景。

interval

public static Flux<Long> interval(Duration delay,
                                  Duration period,
                                  Scheduler timer)
Create a  Flux that emits long values starting with 0 and incrementing at specified time intervals, after an initial delay, on the specified  Scheduler. If demand is not produced in time, an onError will be signalled with an  overflow IllegalStateException detailing the tick that couldn't be emitted. In normal conditions, the  Flux will never complete.

要创建一个Flux,它会从0开始发出long类型的值,并按指定的时间间隔递增。同时在指定的Scheduler上执行,并在初始延迟后开始。如果在规定时间内没有产生足够的请求,则会触发onError信号,并抛出一个IllegalStateException的溢出异常,详细说明无法发出的计时器数值。在正常情况下,Flux将永远不会完成。

Parameters:

delay - the  Duration to wait before emitting 0l
period - the period  Duration before each following increment
timer - a time-capable  Scheduler instance to run on

Returns:

a new  Flux emitting increasing numbers at regular intervals

参数说明:

delay - 在发出第一个 0L 之前等待的时间(Duration 类型)。
period - 每次递增前的时间间隔(Duration 类型)。
timer - 一个支持定时任务的 Scheduler 实例,用于执行任务。

返回值:

返回一个新的 Flux,该 Flux 会以固定的时间间隔发出递增的数字。

Flux.interval(Duration delay, Duration period, Scheduler timer) 是 Reactor 提供的定时工具,它允许你创建一个带有初始延迟的 Flux<Long>,并且指定定时任务的执行频率,同时允许你自定义调度器 Scheduler 来控制这些事件的在哪个线程或线程池上执行。

1. 方法介绍

  • Flux.interval(Duration delay, Duration period, Scheduler timer) 方法会在指定的 delay 延迟时间后开始发射值,并且按照 period 时间间隔发射后续的值。事件的调度是由指定的 Scheduler 控制。

2. 参数

  • delay: 表示初次发射之前的延迟时间。
  • period: 表示每次发射元素之间的时间间隔。
  • timer: 自定义的 Scheduler,用于控制定时器的执行线程。

3. 返回值

  • 返回一个 Flux<Long>,它在初始延迟之后开始发射从 0 开始的递增 Long 值,每隔指定的 period 时间发射一次,使用自定义的 Scheduler 来调度执行。

4. 示例代码

java

import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.time.Duration;

public class IntervalWithDelayAndSchedulerExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Flux,在 2 秒延迟后开始,每隔 1 秒发出一次,在指定的 Scheduler 上运行
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(2), Duration.ofSeconds(1), Schedulers.newSingle("custom-scheduler"));

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 为了展示效果,让主线程等待 10 秒
        Thread.sleep(10000);
    }
}

5. 特性

  • 初始延迟: delay 参数决定了第一次发射值前的等待时间。
  • 时间间隔: period 参数决定了每次发射之间的间隔时间。
  • 自定义调度器: 你可以通过 Scheduler 来决定这些定时任务在哪个线程上执行,比如单线程、并行线程、弹性线程池等。

6. Scheduler 的作用

Scheduler 决定了定时器在哪个线程上运行。不同的 Scheduler 可以提供不同的执行策略:

  • Schedulers.parallel(): 使用并行线程池,适用于 CPU 密集型任务。
  • Schedulers.single(): 使用单线程,适用于顺序执行任务。
  • Schedulers.boundedElastic(): 适合 IO 密集型任务,能够动态调整线程池大小。
  • Schedulers.immediate(): 立即在当前线程执行。
  • Schedulers.fromExecutorService(): 使用自定义的 ExecutorService 作为调度器。

7. 示例:结合 Scheduler 和 take 操作符

示例:初始延迟 3 秒,每隔 1 秒发出一个值,只取前 5 个值
java

import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.time.Duration;

public class IntervalWithDelayAndSchedulerExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Flux,在 3 秒延迟后开始,每隔 1 秒发出一个值,使用自定义 Scheduler,只取前 5 个值
        Flux<Long> intervalFlux = Flux.interval(Duration.ofSeconds(3), Duration.ofSeconds(1), Schedulers.newSingle("custom-scheduler"))
                                      .take(5); // 只取前 5 个值

        // 订阅并打印输出
        intervalFlux.subscribe(i -> System.out.println("Tick: " + i));

        // 等待足够的时间让 Flux 生成数据
        Thread.sleep(8000);
    }
}

输出结果:

(3 秒后)
Tick: 0
Tick: 1
Tick: 2
Tick: 3
Tick: 4

8. 应用场景

  • 定时任务调度: 可以用于实现延迟启动的定时任务,并控制每个任务的执行线程或线程池。
  • 后台服务调度: 适用于需要在特定线程池中运行的定时任务场景,比如资源密集型的后台服务。
  • 网络轮询: 可以用于实现轮询远程服务,在开始前等待一段时间,之后以固定的间隔进行请求。

9. 注意事项

  • 线程安全: 在使用自定义 Scheduler 时,需要注意线程安全问题,尤其是当多个定时任务同时运行时。
  • 资源管理: 使用 Scheduler 时,注意合理选择调度器(比如使用 boundedElastic 处理 IO 密集任务,而不是并行线程池),避免资源浪费。

通过指定 Scheduler,你可以灵活地控制定时任务在哪些线程上执行,并且结合初始延迟和时间间隔,构建出更加复杂的定时任务逻辑。

### Flux与SseEmitter的区别 #### 定义与特性 `Flux` 是 Spring WebFlux 中的核心类型之一,代表了一个可以发出0到N个元素的异步序列[^1]。它遵循反应式流标准,能够很好地与其他反应式库集成,并提供丰富的操作符来处理数据流。 相比之下, `SseEmitter` 则专门用于服务器发送事件(Server-Sent Events),即一种允许服务端主动向客户端推送更新的技术[^2]。通过这种方式,浏览器可以在长时间连接上接收来自服务器的消息通知而无需频繁轮询。 #### 使用场景对比 当涉及到持续的数据传输或实时通信需求时: - **Flux** 更适合于那些需要高效管理背压(Backpressure)以及复杂数据转换逻辑的情况。例如,在微服务架构下进行跨服务调用并聚合多个资源的结果;或是处理大规模并发请求下的高吞吐量业务逻辑。 ```java @GetMapping("/stream-flux") public Flux<String> streamFlux() { return Flux.interval(Duration.ofSeconds(1)) .map(sequence -> "flux-" + sequence); } ``` - **SseEmitter**,另一方面,则适用于更简单的单向消息传递模式——特别是针对HTML5兼容性的网页应用中的即时通讯、股票报价刷新等功能。由于其实现较为直观简单,因此也更容易被开发者理解和部署。 ```java @GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter handleSse() throws InterruptedException { final var emitter = new SseEmitter(); Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { try { emitter.send(SseEmitter.event() .id(String.valueOf(System.currentTimeMillis())) .name("server-time") .data(LocalDateTime.now())); } catch (IOException e) { throw new RuntimeException(e); } }, 0L, 1L, TimeUnit.SECONDS); return emitter; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值