Initial project

This commit is contained in:
Timi
2025-07-14 14:12:45 +08:00
parent c1788c7d30
commit 16e11e30ce
32 changed files with 4945 additions and 94 deletions

View File

@@ -0,0 +1,64 @@
package com.imyeyu.fx.task;
import javafx.concurrent.Task;
/**
* Task 提升权限,所有操作视 UI 线程状态选择性调度UI 繁忙时不更新),数据计算不应在更新回调中
*
* @author 夜雨
* @since 2022-01-08 16:24
*/
abstract class PublicTask<T> extends Task<T> {
/**
* 更新数据
*
* @param value 数据对象
*/
@Override
public void updateValue(T value) {
super.updateValue(value);
}
/**
* 更新消息
*
* @param message 消息
*/
@Override
public void updateMessage(String message) {
super.updateMessage(message);
}
/**
* 更新进度(自动计算百分比)
*
* @param workDone 已完成
* @param max 最大
*/
@Override
public void updateProgress(long workDone, long max) {
super.updateProgress(workDone, max);
}
/**
* 更新进度(自动计算百分比)
*
* @param workDone 已完成
* @param max 最大
*/
@Override
public void updateProgress(double workDone, double max) {
super.updateProgress(workDone, max);
}
/**
* 更新标题
*
* @param title 标题
*/
@Override
public void updateTitle(String title) {
super.updateTitle(title);
}
}

View File

@@ -0,0 +1,301 @@
package com.imyeyu.fx.task;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import com.imyeyu.java.bean.Callback;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.java.bean.CallbackReturn;
/**
* 异步线程执行,常用的构建异步线程任务
*
* <pre>
* // 快速构造
* RunAsync.run(() -> {}); // 快速异步执行 {@link #run(Callback)}
* RunAsync.run(() -> {}, () -> {}); // 快速异步回调 {@link #run(Callback, Callback)}
* RunAsync.run(() -> 100, v -> {}); // 快速异步返回 {@link #callbackReturn(CallbackReturn, CallbackArg)}
* RunAsync.later(() -> {}, 1000); // 延时一秒执行 {@link #later(Callback, long)}
*
* // 标准构造
* new RunAsync&lt;T&gt;() {
*
* &#064;Override
* protected T call() throws Exception {
*
* // 这里不是 FX 线程,可以执行一些长时间的事情
*
* update(new T()); // 主动更新数据
* progress(.6); // 更新进度
* return new T(); // 返回更新数据
* }
*
* &#064;Override
* protected void onUpdate(T t) {
* // 数据更新事件,属于 FX 线程,视 UI 线程状态回调
* }
*
* &#064;Override
* protected void onUpdateProgress(double progress) {
* // 更新进度事件,属于 FX 线程,视 UI 线程状态回调
* }
*
* &#064;Override
* protected void onFinish() {
* // 线程执行完成,属于 FX 线程
* }
*
* &#064;Override
* protected void onException(Throwable e) {
* // 线程异常,属于 FX 线程
* }
* }.start(); &lt;-- 千万别忘了启动任务
* </pre>
*
* @author 夜雨
* @since
*
* @param <T> 数据处理返回类型
*
* @author 夜雨
* @version 2021-02-13 12:56
*/
public abstract class RunAsync<T> extends Service<T> {
/** 任务对象 */
protected PublicTask<T> task;
/** 最近一次更新数据 */
protected T lastT;
protected boolean isInterrupted = false;
@Override
protected Task<T> createTask() {
task = new PublicTask<>() {
protected T call() throws Exception {
return RunAsync.this.call();
}
};
task.setOnScheduled(e -> isInterrupted = false);
task.setOnSucceeded(e -> {
onFinish();
onFinish(lastT);
onFinally();
isInterrupted = false;
});
task.setOnFailed(e -> {
onFinally();
isInterrupted = false;
});
task.valueProperty().addListener((obs, o, t) -> {
lastT = t;
onUpdate(t);
});
task.messageProperty().addListener((obs, o, msg) -> onMessage(msg));
task.progressProperty().addListener((obs, o, p) -> onProgress(p.doubleValue()));
task.exceptionProperty().addListener((obs, o, e) -> onException(e));
return task;
}
/**
* 执行事件(非 FX 线程)
*
* @return 处理结果
* @throws Exception 处理异常
*/
protected abstract T call() throws Exception;
/**
* 主动更新数据,通常是非 FX 线程的 call 里触发,{@link #onUpdate(T)} 里视 UI 线程状态回调
*
* @param t 更新值
*/
protected void update(T t) {
lastT = t;
task.updateValue(t);
}
/**
* 主动更新进度,非 FX 线程的 call 里触发,{@link #onProgress(double)} 里视 UI 线程状态回调
*
* @param progress 进度值
*/
protected void progress(double progress) {
task.updateProgress(progress, 1);
}
/**
* 更新消息,非 FX 线程的 call 里触发,{@link #onMessage(String)} 里视 UI 线程状态回调
*
* @param msg 消息
*/
protected void message(String msg) {
task.updateMessage(msg);
}
/**
* 数据更新事件,{@link #update(T)} 或 {@link #call()} 返回参数触发,属于 FX 线程
*
* @param t 更新数据
*/
protected void onUpdate(T t) {
// 子类实现
}
/**
* 更新进度事件,{@link #progress(double)} 触发,属于 FX 线程
*
* @param progress 进度值
*/
protected void onProgress(double progress) {
// 子类实现
}
/**
* 更新消息
*
* @param msg 消息
*/
protected void onMessage(String msg) {
// 子类实现
}
/** 完成事件FX 线程,只要线程结束就会调用) */
protected void onFinish() {
// 子类实现
}
/**
* 完成事件FX 线程,只要线程结束就会调用,参数为 {@link #update(T)} 或 {@link #call()} 最后一次更新值)
*
* @param t 执行事件返回值
*/
protected void onFinish(T t) {
// 子类实现
}
/**
* 发生异常FX 线程)
*
* @param e 异常
*/
protected void onException(Throwable e) {
e.printStackTrace();
}
/** 线程完成监听,无论正常完成还是出现异常,都会触发此方法 */
protected void onFinally() {
// 子类实现
}
/** 中断任务 */
public void interrupt() {
isInterrupted = true;
}
// ---------- 静态构造 ----------
/**
* 快速构造稍后执行,触发事件属于 FX 线程
*
* @param callback 异步事件
* @param delay 延时时间(毫秒)
*/
public static void later(Callback callback, long delay) {
run(() -> {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, callback);
}
/**
* 快速构造异步任务
*
* @param callback 异步回调
*/
public static void run(Callback callback) {
run(callback, null, null);
}
/**
* 快速构造异步任务
*
* @param asyncCallback 异步回调
* @param finishCallback 异步完成回调
*/
public static void run(Callback asyncCallback, Callback finishCallback) {
run(asyncCallback, finishCallback, null);
}
/**
* 快速构造异步任务
*
* @param asyncCallback 异步回调
* @param exceptionCallback 异常回调
*/
public static void run(Callback asyncCallback, CallbackArg<Throwable> exceptionCallback) {
run(asyncCallback, null, exceptionCallback);
}
/**
* 快速构造异步任务(私有为了可读性,既然主要事件都用上了那应该使用 new {@link RunAsync}() 来保持可读性)
*
* @param asyncCallback 异步回调
* @param finishCallback 异步完成回调
* @param exceptionCallback 异常回调
*/
private static void run(Callback asyncCallback, Callback finishCallback, CallbackArg<Throwable> exceptionCallback) {
new RunAsync<Void>() {
@Override
protected Void call() {
asyncCallback.handler();
return null;
}
@Override
protected void onFinish() {
try {
if (finishCallback != null) {
finishCallback.handler();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onException(Throwable e) {
if (exceptionCallback != null) {
exceptionCallback.handler(e);
}
}
}.start();
}
/**
* 快速构造异步任务
*
* @param asyncCallback 异步回调
* @param finishCallback 异步完成回调
* @param <T> 回调数据类型
*/
public static <T> void callbackReturn(CallbackReturn<T> asyncCallback, CallbackArg<T> finishCallback) {
new RunAsync<T>() {
@Override
protected T call() {
return asyncCallback.handler();
}
@Override
protected void onFinish(T t) {
finishCallback.handler(t);
}
}.start();
}
}

View File

@@ -0,0 +1,65 @@
package com.imyeyu.fx.task;
import javafx.concurrent.Task;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
/**
* 异步守护执行,如果 {@link RunAsync} 超过指定时间没有回调,将触发 onTimeout
*
* @author 夜雨
* @since 2022-01-07 17:33
*/
public abstract class RunAsyncDaemon<T> extends RunAsync<T> {
private final int timeout;
/** true 为回调成功 */
protected boolean isCallBack;
/** 默认构造器(执行超时 2 秒) */
public RunAsyncDaemon() {
this(2000);
}
/**
* 构造器
*
* @param timeout 执行超时限时(毫秒)
*/
public RunAsyncDaemon(int timeout) {
this.timeout = timeout;
}
@Override
protected Task<T> createTask() {
super.createTask();
isCallBack = false;
task.setOnSucceeded(e -> {
onFinish();
onFinish(lastT);
onFinally();
isCallBack = true;
});
task.setOnFailed(e -> {
onFinally();
isCallBack = true;
});
task.setOnRunning(e -> new Thread(() -> {
try {
Thread.sleep(timeout);
if (!isCallBack) {
onTimeout();
}
} catch (InterruptedException ex) {
throw new TimiException(TimiCode.ERROR, "interrupted error", ex);
}
}).start());
return task;
}
/** 超时事件 */
protected abstract void onTimeout();
}

View File

@@ -0,0 +1,352 @@
package com.imyeyu.fx.task;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;
import com.imyeyu.java.bean.Callback;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.java.bean.CallbackReturn;
/**
* 异步任务,支持多次调度
*
* <pre>
* // ---------- 快速构造 ----------
*
* // 每秒执行一次,参数 2 不是 FX 线程
* // {@link RunAsyncScheduled#call(Duration, Callback)}
* RunAsyncScheduled.call(Duration.seconds(1), () -> {});
*
* // 每秒执行一次,参数 2 是 FX 线程
* // {@link RunAsyncScheduled#finish(Duration, Callback)}
* RunAsyncScheduled.finish(Duration.seconds(1), () -> {});
*
* // 动态周期执行,参数 2 不是 FX 线程
* // {@link RunAsyncScheduled#call(CallbackArg, Callback)}
* RunAsyncScheduled.call(scheduled -> {}, () -> {});
*
* // 动态周期执行,参数 2 是 FX 线程
* // {@link RunAsyncScheduled#finish(CallbackArg, Callback)}
* RunAsyncScheduled.finish(scheduled -> {}, () -> {});
*
* // 每秒执行一次并返回,参数 3 FX 线程)的入参是参数 2 (非 FX 线程)的返回
* // {@link RunAsyncScheduled#call(Duration, CallbackReturn, CallbackArg)}
* RunAsyncScheduled.call(Duration.seconds(1), () -> "result", result -> {});
*
* // ---------- 标准构造 ----------
* new RunAsyncScheduled&lt;T&gt;() {
*
* &#064;Override
* protected void onScheduled() {
* // 任务开始后执行,此时可调整任务的周期和延时
* }
*
* &#064;Override
* protected T call() {
* // 这里不是 FX 线程,可以执行一些长时间的事情
*
* update(new T()); // 主动更新数据
* progress(.6); // 更新进度
* return new T(); // 返回更新数据
* }
*
* &#064;Override
* protected void onUpdate(T t) {
* // 数据更新事件,属于 FX 线程,视 UI 线程状态回调
* }
*
* &#064;Override
* protected void onUpdateProgress(double progress) {
* // 更新进度事件,属于 FX 线程,视 UI 线程状态回调
* }
*
* &#064;Override
* protected void onFinish() {
* // 线程执行完成,属于 FX 线程
* }
*
* &#064;Override
* protected void onException(Throwable e) {
* // 线程异常,属于 FX 线程
* }
* }.start(); &lt;-- 千万别忘了启动任务
* </pre>
*
* @author 夜雨
* @since 2022-01-14 17:05
*/
public abstract class RunAsyncScheduled<T> extends ScheduledService<T> {
/** 执行任务 */
protected PublicTask<T> task;
/** 最近一次更新数据 */
protected T lastT;
protected boolean isInterrupted = false;
/** 默认构造器 */
public RunAsyncScheduled() {
}
/**
* 标准构造
*
* @param period 周期
*/
public RunAsyncScheduled(Duration period) {
setPeriod(period);
}
@Override
protected Task<T> createTask() {
task = new PublicTask<>() {
protected T call() throws Exception {
return RunAsyncScheduled.this.call();
}
};
task.setOnScheduled(e -> {
onScheduled();
isInterrupted = false;
});
task.setOnRunning(e -> onRunning());
task.setOnSucceeded(e -> {
onFinish();
onFinish(lastT);
onFinally();
isInterrupted = false;
});
task.setOnFailed(e -> {
onFinally();
isInterrupted = false;
});
task.valueProperty().addListener((obs, o, t) -> {
lastT = t;
onUpdate(t);
});
task.progressProperty().addListener((obs, o, p) -> onUpdateProgress(p.doubleValue()));
task.exceptionProperty().addListener((obs, o, e) -> onException(e));
return task;
}
/**
* 执行事件(非 FX 线程)
*
* @return 处理结果
* @throws Exception 处理异常
*/
protected T call() throws Exception {
// 子类实现
return null;
}
/** 每次开始运行时触发,在延时计算前触发 */
protected void onScheduled() {
// 子类实现
}
/** {@link #call()} 运行时触发 */
protected void onRunning() {
// 子类实现
}
/**
* 主动更新数据,通常是非 FX 线程的 call 里触发,{@link #onUpdate(T)} 里视 UI 线程状态回调
*
* @param t 更新值
*/
protected void update(T t) {
lastT = t;
task.updateValue(t);
}
/**
* 主动更新进度,非 FX 线程的 call 里触发,{@link #onUpdateProgress(double)} 里视 UI 线程状态回调
*
* @param progress 进度值
*/
protected void progress(double progress) {
task.updateProgress(progress, 1);
}
/**
* 数据更新事件,{@link #update(T)} 或 {@link #call()} 返回参数触发,属于 FX 线程
*
* @param t 更新数据
*/
protected void onUpdate(T t) {
// 子类实现
}
/**
* 更新进度事件,{@link #progress(double)} 触发,属于 FX 线程
*
* @param progress 进度值
*/
protected void onUpdateProgress(double progress) {
// 子类实现
}
/** 完成事件FX 线程,只要线程结束就会调用) */
protected void onFinish() {
// 子类实现
}
/**
* 完成事件FX 线程,只要线程结束就会调用,参数为 {@link #update(T)} 或 {@link #call()} 最后一次更新值)
*
* @param t 执行事件返回值
*/
protected void onFinish(T t) {
// 子类实现
}
/** 线程完成监听,无论正常完成还是出现异常,都会触发此方法 */
protected void onFinally() {
// 子类实现
}
/**
* 发生异常FX 线程)
*
* @param e 异常
*/
protected void onException(Throwable e) {
e.printStackTrace();
}
/** 中断任务 */
public void interrupt() {
isInterrupted = true;
}
// ---------- 静态构造 ----------
/**
* 快速构造多次调度任务
*
* @param period 周期
* @param asyncCallback 异步线程执行
* @return 任务
*/
public static RunAsyncScheduled<Void> call(Duration period, Callback asyncCallback) {
RunAsyncScheduled<Void> scheduled = new RunAsyncScheduled<>() {
@Override
protected Void call() {
asyncCallback.handler();
return null;
}
};
scheduled.setPeriod(period);
scheduled.start();
return scheduled;
}
/**
* 快速构造多次调度任务
*
* @param period 周期
* @param asyncCallback 异步线程回调
* @return 任务
*/
public static RunAsyncScheduled<Void> finish(Duration period, Callback asyncCallback) {
RunAsyncScheduled<Void> scheduled = new RunAsyncScheduled<>() {
@Override
protected Void call() throws Exception {
return super.call();
}
@Override
protected void onFinish() {
asyncCallback.handler();
}
};
scheduled.setPeriod(period);
scheduled.start();
return scheduled;
}
/**
* 快速构造多次调度任务
*
* @param period 周期
* @param asyncCallback 异步线程执行
* @param finishCallback 异步线程执行完成回调
* @return 任务
* @param <T> 执行数据回调
*/
public static <T> RunAsyncScheduled<T> call(Duration period, CallbackReturn<T> asyncCallback, CallbackArg<T> finishCallback) {
RunAsyncScheduled<T> scheduled = new RunAsyncScheduled<>() {
@Override
protected T call() {
return asyncCallback.handler();
}
@Override
protected void onFinish(T t) {
finishCallback.handler(t);
}
};
scheduled.setPeriod(period);
scheduled.start();
return scheduled;
}
/**
* 快速构造动态周期调度任务
*
* @param scheduleEvent 执行前调度,可重置执行周期
* @param asyncCallback 异步线程执行
* @return 任务
*/
public static RunAsyncScheduled<Void> call(CallbackArg<RunAsyncScheduled<Void>> scheduleEvent, Callback asyncCallback) {
RunAsyncScheduled<Void> scheduled = new RunAsyncScheduled<>() {
@Override
protected void onScheduled() {
scheduleEvent.handler(this);
}
@Override
protected Void call() {
asyncCallback.handler();
return null;
}
};
scheduled.start();
return scheduled;
}
/**
* 快速构造多次调度任务
*
* @param scheduleEvent 执行前调度,可重置执行周期
* @param finishCallback 异步线程执行完成回调
* @return 任务
*/
public static RunAsyncScheduled<Void> finish(CallbackArg<RunAsyncScheduled<Void>> scheduleEvent, Callback finishCallback) {
RunAsyncScheduled<Void> scheduled = new RunAsyncScheduled<>() {
@Override
protected void onScheduled() {
scheduleEvent.handler(this);
}
@Override
protected Void call() {
return null;
}
@Override
protected void onFinish() {
finishCallback.handler();
}
};
scheduled.start();
return scheduled;
}
}