299 lines
7.1 KiB
Java
299 lines
7.1 KiB
Java
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<T>() {
|
||
*
|
||
* @Override
|
||
* protected T call() throws Exception {
|
||
*
|
||
* // 这里不是 FX 线程,可以执行一些长时间的事情
|
||
*
|
||
* update(new T()); // 主动更新数据
|
||
* progress(.6); // 更新进度
|
||
* return new T(); // 返回更新数据
|
||
* }
|
||
*
|
||
* @Override
|
||
* protected void onUpdate(T t) {
|
||
* // 数据更新事件,属于 FX 线程,视 UI 线程状态回调
|
||
* }
|
||
*
|
||
* @Override
|
||
* protected void onUpdateProgress(double progress) {
|
||
* // 更新进度事件,属于 FX 线程,视 UI 线程状态回调
|
||
* }
|
||
*
|
||
* @Override
|
||
* protected void onFinish() {
|
||
* // 线程执行完成,属于 FX 线程
|
||
* }
|
||
*
|
||
* @Override
|
||
* protected void onException(Throwable e) {
|
||
* // 线程异常,属于 FX 线程
|
||
* }
|
||
* }.start(); <-- 千万别忘了启动任务
|
||
* </pre>
|
||
*
|
||
* @author 夜雨
|
||
* @since 2021-02-13 12:56
|
||
* @param <T> 数据处理返回类型
|
||
*/
|
||
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;
|
||
cancel();
|
||
}
|
||
|
||
// ---------- 静态构造 ----------
|
||
|
||
/**
|
||
* 快速构造稍后执行,触发事件属于 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();
|
||
}
|
||
}
|