Flink 窗口触发器(Trigger)(一)

Flink 窗口触发器(Trigger)(一)
Flink 窗口触发器(Trigger)(二)

Flink的窗口触发器(Trigger)是流处理中一个非常关键的概念,它定义了窗口何时被触发并决定触发后的行为(如进行窗口数据的计算或清理)。

一、基本概念

  • 定义:触发器决定了窗口何时被触发以及触发后的行为。在Flink中,窗口的触发是通过设置定时器来实现的。
  • 作用:控制窗口数据的聚合时机,确保数据在适当的时间点被处理和输出。
    在这里插入图片描述

二、类型

Flink提供了多种内置的触发器,以下几种为常用类型:

  1. EventTimeTrigger
  • 工作原理:基于事件时间和水印(Watermark)机制来触发窗口计算。当窗口的最大时间戳小于等于当前的水印时,立即触发窗口计算。
  • 适用场景:适用于需要基于事件时间进行处理的场景,如金融交易、日志分析等。
  1. ProcessingTimeTrigger
  • 工作原理:基于处理时间(即机器的系统时间)来触发窗口计算。当处理时间达到窗口的结束时间时,触发窗口计算。
  • 适用场景:适用于对时间精度要求不高的场景,或者当事件时间无法准确获取时。
  1. CountTrigger
  • 工作原理:根据窗口内元素的数量来触发计算。当窗口内的元素数量达到预设的阈值时,触发窗口计算。
  • 适用场景:适用于需要基于数据量进行处理的场景,如批量数据处理、流量分析等。
  1. ContinuousEventTimeTriggerContinuousProcessingTimeTrigger
  • 工作原理:根据间隔时间周期性触发窗口计算,或者当窗口的结束时间小于当前的时间(事件时间或处理时间)时触发计算。
  • 适用场景:适用于需要周期性处理数据的场景,如实时监控、周期性报表等。
  1. DeltaTrigger
  • 工作原理:根据接入数据计算出的Delta指标是否超过指定的阈值来触发窗口计算。
  • 适用场景:适用于需要基于数据变化量进行处理的场景,如异常检测、趋势分析等。
  1. PurgingTrigger
  • 工作原理:将其他触发器作为参数转换为Purge类型的触发器,在触发计算后清除窗口内的数据。
  • 适用场景:适用于需要在计算完成后立即清除窗口数据的场景,以节省存储空间。

三、关键方法

触发器通常包含以下几个关键方法:

  1. onElement(T element, long timestamp, W window, TriggerContext ctx)
    当元素被添加到窗口时调用,用于注册定时器或更新窗口状态。
  2. onEventTime(long time, W window, TriggerContext ctx)
    当事件时间计时器触发时调用,用于处理事件时间相关的触发逻辑。
  3. onProcessingTime(long time, W window, TriggerContext ctx)
    当处理时间计时器触发时调用,用于处理处理时间相关的触发逻辑。
  4. onMerge(W window, OnMergeContext ctx)(可选)
    当两个窗口合并时调用,用于合并窗口的状态和定时器。
  5. clear(W window, TriggerContext ctx)
    当窗口被删除时调用,用于清理窗口的状态和定时器。

四、行为

触发器在触发时会返回一个TriggerResult枚举值,以决定窗口的后续行为。常见的TriggerResult值包括:

  • CONTINUE:表示不进行任何操作,等待下一个触发条件。
  • FIRE:表示触发窗口计算并输出结果,但窗口状态保持不变。
  • PURGE:表示不触发窗口计算,只清除窗口内的数据和状态。
  • FIRE_AND_PURGE:表示触发窗口计算并输出结果,然后清除窗口内的数据和状态。

Flink的窗口触发器是流处理中非常灵活且强大的工具,它允许开发者根据实际需求定义窗口的触发条件和触发后的行为。通过选择合适的触发器和配置相应的参数,可以实现高效、准确的流数据处理。

五、Trigger

EventTimeTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;@PublicEvolving
public class EventTimeTrigger extends Trigger<Object, TimeWindow> {private static final long serialVersionUID = 1L;private EventTimeTrigger() {}public TriggerResult onElement(Object element, long timestamp, TimeWindow window, Trigger.TriggerContext ctx) throws Exception {if (window.maxTimestamp() <= ctx.getCurrentWatermark()) {return TriggerResult.FIRE;} else {ctx.registerEventTimeTimer(window.maxTimestamp());return TriggerResult.CONTINUE;}}public TriggerResult onEventTime(long time, TimeWindow window, Trigger.TriggerContext ctx) {return time == window.maxTimestamp() ? TriggerResult.FIRE : TriggerResult.CONTINUE;}public TriggerResult onProcessingTime(long time, TimeWindow window, Trigger.TriggerContext ctx) throws Exception {return TriggerResult.CONTINUE;}public void clear(TimeWindow window, Trigger.TriggerContext ctx) throws Exception {ctx.deleteEventTimeTimer(window.maxTimestamp());}public boolean canMerge() {return true;}public void onMerge(TimeWindow window, Trigger.OnMergeContext ctx) {long windowMaxTimestamp = window.maxTimestamp();if (windowMaxTimestamp > ctx.getCurrentWatermark()) {ctx.registerEventTimeTimer(windowMaxTimestamp);}}public String toString() {return "EventTimeTrigger()";}public static EventTimeTrigger create() {return new EventTimeTrigger();}
}

ProcessingTimeTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;@PublicEvolving
public class ProcessingTimeTrigger extends Trigger<Object, TimeWindow> {private static final long serialVersionUID = 1L;private ProcessingTimeTrigger() {}public TriggerResult onElement(Object element, long timestamp, TimeWindow window, Trigger.TriggerContext ctx) {ctx.registerProcessingTimeTimer(window.maxTimestamp());return TriggerResult.CONTINUE;}public TriggerResult onEventTime(long time, TimeWindow window, Trigger.TriggerContext ctx) throws Exception {return TriggerResult.CONTINUE;}public TriggerResult onProcessingTime(long time, TimeWindow window, Trigger.TriggerContext ctx) {return TriggerResult.FIRE;}public void clear(TimeWindow window, Trigger.TriggerContext ctx) throws Exception {ctx.deleteProcessingTimeTimer(window.maxTimestamp());}public boolean canMerge() {return true;}public void onMerge(TimeWindow window, Trigger.OnMergeContext ctx) {long windowMaxTimestamp = window.maxTimestamp();if (windowMaxTimestamp > ctx.getCurrentProcessingTime()) {ctx.registerProcessingTimeTimer(windowMaxTimestamp);}}public String toString() {return "ProcessingTimeTrigger()";}public static ProcessingTimeTrigger create() {return new ProcessingTimeTrigger();}
}

ProcessingTimeoutTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import java.time.Duration;
import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeutils.base.LongSerializer;
import org.apache.flink.streaming.api.windowing.windows.Window;@PublicEvolving
public class ProcessingTimeoutTrigger<T, W extends Window> extends Trigger<T, W> {private static final long serialVersionUID = 1L;private final Trigger<T, W> nestedTrigger;private final long interval;private final boolean resetTimerOnNewRecord;private final boolean shouldClearOnTimeout;private final ValueStateDescriptor<Long> timeoutStateDesc;private ProcessingTimeoutTrigger(Trigger<T, W> nestedTrigger, long interval, boolean resetTimerOnNewRecord, boolean shouldClearOnTimeout) {this.nestedTrigger = nestedTrigger;this.interval = interval;this.resetTimerOnNewRecord = resetTimerOnNewRecord;this.shouldClearOnTimeout = shouldClearOnTimeout;this.timeoutStateDesc = new ValueStateDescriptor("timeout", LongSerializer.INSTANCE);}public TriggerResult onElement(T element, long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {TriggerResult triggerResult = this.nestedTrigger.onElement(element, timestamp, window, ctx);if (triggerResult.isFire()) {this.clear(window, ctx);return triggerResult;} else {ValueState<Long> timeoutState = (ValueState)ctx.getPartitionedState(this.timeoutStateDesc);long nextFireTimestamp = ctx.getCurrentProcessingTime() + this.interval;Long timeoutTimestamp = (Long)timeoutState.value();if (timeoutTimestamp != null && this.resetTimerOnNewRecord) {ctx.deleteProcessingTimeTimer(timeoutTimestamp);timeoutState.clear();timeoutTimestamp = null;}if (timeoutTimestamp == null) {timeoutState.update(nextFireTimestamp);ctx.registerProcessingTimeTimer(nextFireTimestamp);}return triggerResult;}}public TriggerResult onProcessingTime(long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {TriggerResult triggerResult = this.nestedTrigger.onProcessingTime(timestamp, window, ctx);if (this.shouldClearOnTimeout) {this.clear(window, ctx);}return triggerResult.isPurge() ? TriggerResult.FIRE_AND_PURGE : TriggerResult.FIRE;}public TriggerResult onEventTime(long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {TriggerResult triggerResult = this.nestedTrigger.onEventTime(timestamp, window, ctx);if (this.shouldClearOnTimeout) {this.clear(window, ctx);}return triggerResult.isPurge() ? TriggerResult.FIRE_AND_PURGE : TriggerResult.FIRE;}public void clear(W window, Trigger.TriggerContext ctx) throws Exception {ValueState<Long> timeoutTimestampState = (ValueState)ctx.getPartitionedState(this.timeoutStateDesc);Long timeoutTimestamp = (Long)timeoutTimestampState.value();if (timeoutTimestamp != null) {ctx.deleteProcessingTimeTimer(timeoutTimestamp);timeoutTimestampState.clear();}this.nestedTrigger.clear(window, ctx);}public String toString() {return "TimeoutTrigger(" + this.nestedTrigger.toString() + ")";}public static <T, W extends Window> ProcessingTimeoutTrigger<T, W> of(Trigger<T, W> nestedTrigger, Duration timeout) {return new ProcessingTimeoutTrigger(nestedTrigger, timeout.toMillis(), false, true);}public static <T, W extends Window> ProcessingTimeoutTrigger<T, W> of(Trigger<T, W> nestedTrigger, Duration timeout, boolean resetTimerOnNewRecord, boolean shouldClearOnTimeout) {return new ProcessingTimeoutTrigger(nestedTrigger, timeout.toMillis(), resetTimerOnNewRecord, shouldClearOnTimeout);}
}

CountTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.state.ReducingState;
import org.apache.flink.api.common.state.ReducingStateDescriptor;
import org.apache.flink.api.common.typeutils.base.LongSerializer;
import org.apache.flink.streaming.api.windowing.windows.Window;@PublicEvolving
public class CountTrigger<W extends Window> extends Trigger<Object, W> {private static final long serialVersionUID = 1L;private final long maxCount;private final ReducingStateDescriptor<Long> stateDesc;private CountTrigger(long maxCount) {this.stateDesc = new ReducingStateDescriptor("count", new Sum(), LongSerializer.INSTANCE);this.maxCount = maxCount;}public TriggerResult onElement(Object element, long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {ReducingState<Long> count = (ReducingState)ctx.getPartitionedState(this.stateDesc);count.add(1L);if ((Long)count.get() >= this.maxCount) {count.clear();return TriggerResult.FIRE;} else {return TriggerResult.CONTINUE;}}public TriggerResult onEventTime(long time, W window, Trigger.TriggerContext ctx) {return TriggerResult.CONTINUE;}public TriggerResult onProcessingTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {return TriggerResult.CONTINUE;}public void clear(W window, Trigger.TriggerContext ctx) throws Exception {((ReducingState)ctx.getPartitionedState(this.stateDesc)).clear();}public boolean canMerge() {return true;}public void onMerge(W window, Trigger.OnMergeContext ctx) throws Exception {ctx.mergePartitionedState(this.stateDesc);}public String toString() {return "CountTrigger(" + this.maxCount + ")";}public static <W extends Window> CountTrigger<W> of(long maxCount) {return new CountTrigger(maxCount);}private static class Sum implements ReduceFunction<Long> {private static final long serialVersionUID = 1L;private Sum() {}public Long reduce(Long value1, Long value2) throws Exception {return value1 + value2;}}
}

ContinuousEventTimeTrigger和ContinuousProcessingTimeTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.state.ReducingState;
import org.apache.flink.api.common.state.ReducingStateDescriptor;
import org.apache.flink.api.common.typeutils.base.LongSerializer;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.Window;@PublicEvolving
public class ContinuousEventTimeTrigger<W extends Window> extends Trigger<Object, W> {private static final long serialVersionUID = 1L;private final long interval;private final ReducingStateDescriptor<Long> stateDesc;private ContinuousEventTimeTrigger(long interval) {this.stateDesc = new ReducingStateDescriptor("fire-time", new Min(), LongSerializer.INSTANCE);this.interval = interval;}public TriggerResult onElement(Object element, long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {if (window.maxTimestamp() <= ctx.getCurrentWatermark()) {return TriggerResult.FIRE;} else {ctx.registerEventTimeTimer(window.maxTimestamp());ReducingState<Long> fireTimestampState = (ReducingState)ctx.getPartitionedState(this.stateDesc);if (fireTimestampState.get() == null) {this.registerNextFireTimestamp(timestamp - timestamp % this.interval, window, ctx, fireTimestampState);}return TriggerResult.CONTINUE;}}public TriggerResult onEventTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {if (time == window.maxTimestamp()) {return TriggerResult.FIRE;} else {ReducingState<Long> fireTimestampState = (ReducingState)ctx.getPartitionedState(this.stateDesc);Long fireTimestamp = (Long)fireTimestampState.get();if (fireTimestamp != null && fireTimestamp == time) {fireTimestampState.clear();this.registerNextFireTimestamp(time, window, ctx, fireTimestampState);return TriggerResult.FIRE;} else {return TriggerResult.CONTINUE;}}}public TriggerResult onProcessingTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {return TriggerResult.CONTINUE;}public void clear(W window, Trigger.TriggerContext ctx) throws Exception {ReducingState<Long> fireTimestamp = (ReducingState)ctx.getPartitionedState(this.stateDesc);Long timestamp = (Long)fireTimestamp.get();if (timestamp != null) {ctx.deleteEventTimeTimer(timestamp);fireTimestamp.clear();}}public boolean canMerge() {return true;}public void onMerge(W window, Trigger.OnMergeContext ctx) throws Exception {ctx.mergePartitionedState(this.stateDesc);Long nextFireTimestamp = (Long)((ReducingState)ctx.getPartitionedState(this.stateDesc)).get();if (nextFireTimestamp != null) {ctx.registerEventTimeTimer(nextFireTimestamp);}}public String toString() {return "ContinuousEventTimeTrigger(" + this.interval + ")";}@VisibleForTestingpublic long getInterval() {return this.interval;}public static <W extends Window> ContinuousEventTimeTrigger<W> of(Time interval) {return new ContinuousEventTimeTrigger(interval.toMilliseconds());}private void registerNextFireTimestamp(long time, W window, Trigger.TriggerContext ctx, ReducingState<Long> fireTimestampState) throws Exception {long nextFireTimestamp = Math.min(time + this.interval, window.maxTimestamp());fireTimestampState.add(nextFireTimestamp);ctx.registerEventTimeTimer(nextFireTimestamp);}private static class Min implements ReduceFunction<Long> {private static final long serialVersionUID = 1L;private Min() {}public Long reduce(Long value1, Long value2) throws Exception {return Math.min(value1, value2);}}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.state.ReducingState;
import org.apache.flink.api.common.state.ReducingStateDescriptor;
import org.apache.flink.api.common.typeutils.base.LongSerializer;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.Window;@PublicEvolving
public class ContinuousProcessingTimeTrigger<W extends Window> extends Trigger<Object, W> {private static final long serialVersionUID = 1L;private final long interval;private final ReducingStateDescriptor<Long> stateDesc;private ContinuousProcessingTimeTrigger(long interval) {this.stateDesc = new ReducingStateDescriptor("fire-time", new Min(), LongSerializer.INSTANCE);this.interval = interval;}public TriggerResult onElement(Object element, long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {ReducingState<Long> fireTimestampState = (ReducingState)ctx.getPartitionedState(this.stateDesc);timestamp = ctx.getCurrentProcessingTime();if (fireTimestampState.get() == null) {this.registerNextFireTimestamp(timestamp - timestamp % this.interval, window, ctx, fireTimestampState);}return TriggerResult.CONTINUE;}public TriggerResult onEventTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {return TriggerResult.CONTINUE;}public TriggerResult onProcessingTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {ReducingState<Long> fireTimestampState = (ReducingState)ctx.getPartitionedState(this.stateDesc);if (((Long)fireTimestampState.get()).equals(time)) {fireTimestampState.clear();this.registerNextFireTimestamp(time, window, ctx, fireTimestampState);return TriggerResult.FIRE;} else {return TriggerResult.CONTINUE;}}public void clear(W window, Trigger.TriggerContext ctx) throws Exception {ReducingState<Long> fireTimestamp = (ReducingState)ctx.getPartitionedState(this.stateDesc);Long timestamp = (Long)fireTimestamp.get();if (timestamp != null) {ctx.deleteProcessingTimeTimer(timestamp);fireTimestamp.clear();}}public boolean canMerge() {return true;}public void onMerge(W window, Trigger.OnMergeContext ctx) throws Exception {ctx.mergePartitionedState(this.stateDesc);Long nextFireTimestamp = (Long)((ReducingState)ctx.getPartitionedState(this.stateDesc)).get();if (nextFireTimestamp != null) {ctx.registerProcessingTimeTimer(nextFireTimestamp);}}@VisibleForTestingpublic long getInterval() {return this.interval;}public String toString() {return "ContinuousProcessingTimeTrigger(" + this.interval + ")";}public static <W extends Window> ContinuousProcessingTimeTrigger<W> of(Time interval) {return new ContinuousProcessingTimeTrigger(interval.toMilliseconds());}private void registerNextFireTimestamp(long time, W window, Trigger.TriggerContext ctx, ReducingState<Long> fireTimestampState) throws Exception {long nextFireTimestamp = Math.min(time + this.interval, window.maxTimestamp());fireTimestampState.add(nextFireTimestamp);ctx.registerProcessingTimeTimer(nextFireTimestamp);}private static class Min implements ReduceFunction<Long> {private static final long serialVersionUID = 1L;private Min() {}public Long reduce(Long value1, Long value2) throws Exception {return Math.min(value1, value2);}}
}

DeltaTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeutils.TypeSerializer;
import org.apache.flink.streaming.api.functions.windowing.delta.DeltaFunction;
import org.apache.flink.streaming.api.windowing.windows.Window;@PublicEvolving
public class DeltaTrigger<T, W extends Window> extends Trigger<T, W> {private static final long serialVersionUID = 1L;private final DeltaFunction<T> deltaFunction;private final double threshold;private final ValueStateDescriptor<T> stateDesc;private DeltaTrigger(double threshold, DeltaFunction<T> deltaFunction, TypeSerializer<T> stateSerializer) {this.deltaFunction = deltaFunction;this.threshold = threshold;this.stateDesc = new ValueStateDescriptor("last-element", stateSerializer);}public TriggerResult onElement(T element, long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {ValueState<T> lastElementState = (ValueState)ctx.getPartitionedState(this.stateDesc);if (lastElementState.value() == null) {lastElementState.update(element);return TriggerResult.CONTINUE;} else if (this.deltaFunction.getDelta(lastElementState.value(), element) > this.threshold) {lastElementState.update(element);return TriggerResult.FIRE;} else {return TriggerResult.CONTINUE;}}public TriggerResult onEventTime(long time, W window, Trigger.TriggerContext ctx) {return TriggerResult.CONTINUE;}public TriggerResult onProcessingTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {return TriggerResult.CONTINUE;}public void clear(W window, Trigger.TriggerContext ctx) throws Exception {((ValueState)ctx.getPartitionedState(this.stateDesc)).clear();}public String toString() {return "DeltaTrigger(" + this.deltaFunction + ", " + this.threshold + ")";}public static <T, W extends Window> DeltaTrigger<T, W> of(double threshold, DeltaFunction<T> deltaFunction, TypeSerializer<T> stateSerializer) {return new DeltaTrigger(threshold, deltaFunction, stateSerializer);}
}

PurgingTrigger

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.apache.flink.streaming.api.windowing.triggers;import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.streaming.api.windowing.windows.Window;@PublicEvolving
public class PurgingTrigger<T, W extends Window> extends Trigger<T, W> {private static final long serialVersionUID = 1L;private Trigger<T, W> nestedTrigger;private PurgingTrigger(Trigger<T, W> nestedTrigger) {this.nestedTrigger = nestedTrigger;}public TriggerResult onElement(T element, long timestamp, W window, Trigger.TriggerContext ctx) throws Exception {TriggerResult triggerResult = this.nestedTrigger.onElement(element, timestamp, window, ctx);return triggerResult.isFire() ? TriggerResult.FIRE_AND_PURGE : triggerResult;}public TriggerResult onEventTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {TriggerResult triggerResult = this.nestedTrigger.onEventTime(time, window, ctx);return triggerResult.isFire() ? TriggerResult.FIRE_AND_PURGE : triggerResult;}public TriggerResult onProcessingTime(long time, W window, Trigger.TriggerContext ctx) throws Exception {TriggerResult triggerResult = this.nestedTrigger.onProcessingTime(time, window, ctx);return triggerResult.isFire() ? TriggerResult.FIRE_AND_PURGE : triggerResult;}public void clear(W window, Trigger.TriggerContext ctx) throws Exception {this.nestedTrigger.clear(window, ctx);}public boolean canMerge() {return this.nestedTrigger.canMerge();}public void onMerge(W window, Trigger.OnMergeContext ctx) throws Exception {this.nestedTrigger.onMerge(window, ctx);}public String toString() {return "PurgingTrigger(" + this.nestedTrigger.toString() + ")";}public static <T, W extends Window> PurgingTrigger<T, W> of(Trigger<T, W> nestedTrigger) {return new PurgingTrigger(nestedTrigger);}@VisibleForTestingpublic Trigger<T, W> getNestedTrigger() {return this.nestedTrigger;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[数据集][目标检测]人员状态跑睡抽烟打电话跌倒检测数据集4943张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4943 标注数量(xml文件个数)&#xff1a;4943 标注数量(txt文件个数)&#xff1a;4943 标注…

[Leetcode 136][Easy]-只出现一次的数字

目录 题目描述 具体思路 题目描述 原题链接 具体思路 ①首先看到数组中重复的数字&#xff0c;想到快慢指针&#xff0c;但是数组的元素是乱序的不好求。因此先对数组排序。使用了STL库的sort函数&#xff0c;时间复杂度O(nlogn)不符合题目要求&#xff0c;空间复杂度O(1)。…

RXMH2 RK223 069 AS大容量中间继电器 板前接线 约瑟JOSEF

RXMH2大容量中间继电器型号&#xff1a; RXMH2 RK 223 067大容量中间继电器&#xff1b; RXMH2 RK 223 068大容量中间继电器&#xff1b; RXMH2 RK 223 069大容量中间继电器&#xff1b; RXMH2 RK 223 070大容量中间继电器&#xff1b; 用途 用于电力系统二次回路及工业自…

Ubuntu22.04上Docker的安装

1. 使用APT安装 首先安装HTTPS传输的软件包和CA证书&#xff0c;确保软件下载过程中不被篡改。 sudo apt-get updatesudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release -y然后&#xff0c;使用国内源&#xff0c;并添加软件源的 GPG 密钥以防…

Vue2和Vue3的区别Vue3的组合式API

一、Vue2和Vue3的区别 1、创建方式的不同&#xff1a; &#xff08;1&#xff09;、vue2:是一个构造函数&#xff0c;通过该构造函数创建一个Vue实例 new Vue({})&#xff08;2&#xff09;、Vue3:是一个对象。并通过该对象的createApp()方法&#xff0c;创建一个vue实例。 Vue…

RAG技术下的文档智能检索

在数字化浪潮的推动下&#xff0c;信息检索已成为我们日常生活中不可或缺的一部分。然而&#xff0c;随着数据量的爆炸式增长&#xff0c;如何快速精准地从海量文档中检索出有价值的信息&#xff0c;成为了一个巨大的挑战。本文将带您走进 Pinecone 向量数据库的世界&#xff0…

AIGC到底如何改变创意设计?

在当今数字化时代&#xff0c;AIGC&#xff08;生成式人工智能&#xff09;技术的崛起对创意设计领域产生了深远的影响。AIGC不仅为设计师提供了新的工具和方法&#xff0c;还改变了传统的设计流程和思维方式。 传统的设计过程中&#xff0c;设计师需要耗费大量时间在绘图、修…

npm install puppeteer 报错 npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated解决办法

npm install puppeteer 报错如下&#xff1a; npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated. Use PUPPETEER_DOWNLOAD_BASE_URL instead. npm ERR! Error: ERROR: Failed to set up Chrome v126.0.6478.126! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to sk…

【Linux进程】僵尸进程与孤儿进程

前言 僵尸进程和孤儿进程是Linux中极为重要的两个种进程状态, 本文将会围绕这三个问题: 是什么? 为什么? 如何产生的? 详细的介绍这两种进程; 以及一些使用场景. 僵尸进程 在了解孤儿进程之前, 需要先引入僵尸进程的概念; 什么是僵尸进程? 僵尸进程: 就是处于僵死状态的进…

类似Jira的在线项目管理软件有哪些?10 个主流的Jira替代方案

10 个 Jira 替代方案&#xff1a;PingCode、Worktile、Teambition、Redmine、Asana、monday.com、Zoho Projects、思码逸、Notion、Airtable。 Jira 是一款流行的项目管理工具&#xff0c;专为产品开发团队而设计。虽然它是一种多功能解决方案&#xff0c;几乎适用于任何类型的…

Git 操作补充:变基

变基 在 Git 中&#xff0c;整合来自不同分支的修改&#xff0c;除了 merge&#xff0c;还有一种方法&#xff0c;变基 rebase。git rebase 命令基本是是一个自动化的 cherry-pick 命令&#xff0c;它计算出一系列的提交&#xff0c;然后在其他地方以同样的顺序一个一个的 che…

流程表单设计器开源优势多 助力实现流程化!

实现流程化办公是很多职场企业的发展目标。应用什么样的软件可以实现这一目的&#xff1f;低代码技术平台、流程表单设计器开源的优势特点多&#xff0c;在推动企业降本增效、流程化办公的过程中作用明显&#xff0c;是理想的软件平台。那么&#xff0c;流程表单设计器开源的优…

编译Open Cascade(OCC)并使用C#进行开发

说明&#xff1a; VS版本&#xff1a;Visual Studio Community 2022系统&#xff1a;Windows 11 专业版23H2Open CASCADE&#xff1a;v7.7.0&#xff08;链接&#xff1a;https://pan.baidu.com/s/1-o1s4z3cjpYf5XkwhSDspQ?pwdp9i5提取码&#xff1a;p9i5&#xff09; 下载和…

python数据分析入门学习笔记

目录 一、 数据分析有关的python库简介 (一)numpy (二)pandas (三)matplotlib (四)scipy (五)statsmodels (六)scikit-learn 二、 数据的导入和导出 三、 数据筛选 四、 数据描述 五、 数据处理 六、 统计分析 七、 可视化 八、 其它![](https://…

windows电脑蓝屏解决方法(亲测有效)

如果不是硬件问题&#xff0c;打开终端尝试以下命令 sfc /scannow DISM /Online /Cleanup-Image /RestoreHealth

If you already have a 64-bit JDK installed ,defined a JAVA_HOME...的错误

今天感觉idea有点卡&#xff0c;修改了一下内存&#xff0c;结果就报这个错误了&#xff0c;网上的解决方案好多&#xff0c;都不行 以下是解决方案 打开 C:\Program Files\JetBrains\IntelliJ IDEA 2024.1.4\bin\jetbrains_client64.exe 把jihuo这个目录下所有的文件都删掉&…

通过easyexcel导入数据,添加表格参数的校验,同表格内校验以及和已有数据的校验

引入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.11</version><scope>compile</scope></dependency> 需要导入到某个目录下 如果产品名称相同&#xff0c…

Mybatis数据封装

目录 解决方案&#xff1a; 1.起别名&#xff1a; 2.手动结果映射&#xff1a; 3.开启驼峰命名(推荐)&#xff1a; 我们看到查询返回的结果中大部分字段是有值的&#xff0c;但是deptId&#xff0c;createTime&#xff0c;updateTime这几个字段是没有值的&#xff0c;而数据…

分析数据不要太老实,有BI方案就用起来——奥威BI软件

在当今数据驱动的时代&#xff0c;企业对于数据分析的需求日益迫切。然而&#xff0c;面对海量的数据和复杂的分析需求&#xff0c;许多企业仍停留在传统的手工分析模式&#xff0c;这不仅效率低下&#xff0c;还容易出错。幸运的是&#xff0c;像奥威BI这样的数据分析软件提供…

【深度学习】扫描全能王的AI驱动创新与智能高清滤镜技术解析

目录 引言1、扫描全能王2、智能高清滤镜黑科技2.1、图像视觉矫正2.2、去干扰技术 3、实际应用案例3.1、打印文稿褶皱检测3.2、试卷擦除手写3.3、老旧文件处理3.4、收银小票3.5、从不同角度扫描文档 4、用户体验结论与未来展望 引言 在数字化时代背景下&#xff0c;文档扫描功能…