一、什么是异步回调
当一个异步操作被触发时,程序可以继续执行后续代码而不必等待该操作完成。一旦异步操作完成(无论是成功还是失败),会调用一个事先定义好的函数,这个函数就是“回调函数”。回调函数会处理异步操作的结果(比如处理数据或者处理错误)。
二、自己一步步实现一个异步回调架子
2.1 最基础版本
首先,定义一个异步任务接口,该接口代表了将要异步执行的任务。
@FunctionalInterface
public interface AsyncTask<T> {
T execute() throws Exception;
}
定义回调接口
public interface Callback<T> {
void onSuccess(T result);
void onFailure(Exception e);
}
实现异步任务执行器
public class AsyncTaskExecutor {
public <T> void executeAsync(AsyncTask<T> task, Callback<T> callback) {
new Thread(() -> {
try {
T result = task.execute(); // 执行异步任务
callback.onSuccess(result); // 调用成功回调
} catch (Exception e) {
callback.onFailure(e); // 调用失败回调
}
}).start();
}
}
2.2 使用线程池处理提交的任务
改进AsyncTaskExecutor
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AsyncTaskExecutor {
private final ExecutorService executor;
public AsyncTaskExecutor(int numberOfThreads) {
this.executor = Executors.newFixedThreadPool(numberOfThreads);
}
public <T> void executeAsync(AsyncTask<T> task, Callback<T> callback) {
executor.submit(() -> {
try {
T result = task.execute(); // 执行异步任务
callback.onSuccess(result); // 调用成功回调
} catch (Exception e) {
callback.onFailure(e); // 调用失败回调
}
});
}
public void shutdown() {
executor.shutdown();
}
}
2.3 使用单独的线程池执行回调
改进AsyncTaskExecutor
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AsyncTaskExecutor {
private final ExecutorService taskExecutor;
private final ExecutorService callbackExecutor;
public AsyncTaskExecutor(int taskThreads, int callbackThreads) {
this.taskExecutor = Executors.newFixedThreadPool(taskThreads);
this.callbackExecutor = Executors.newFixedThreadPool(callbackThreads);
}
public <T> void executeAsync(AsyncTask<T> task, Callback<T> callback) {
taskExecutor.submit(() -> {
try {
T result = task.execute(); // 在任务线程池中执行异步任务
callbackExecutor.submit(() -> callback.onSuccess(result)); // 在回调线程池中执行成功回调
} catch (Exception e) {
callbackExecutor.submit(() -> callback.onFailure(e)); // 在回调线程池中执行失败回调
}
});
}
public void shutdown() {
// 关闭两个线程池
try {
taskExecutor.shutdown();
callbackExecutor.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.4 支持取消异步任务
利用Future接口提供的取消机制。当通过线程池提交一个任务时,它会返回一个Future对象,可以使用这个对象来取消任务或检查任务是否已经完成或被取消。
改进AsyncTaskExecutor
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class AsyncTaskExecutor {
private final ExecutorService taskExecutor;
private final ExecutorService callbackExecutor;
public AsyncTaskExecutor(int taskThreads, int callbackThreads) {
this.taskExecutor = Executors.newFixedThreadPool(taskThreads);
this.callbackExecutor = Executors.newFixedThreadPool(callbackThreads);
}
public <T> Future<?> executeAsync(AsyncTask<T> task, Callback<T> callback) {
return taskExecutor.submit(() -> {
try {
T result = task.execute(); // 在任务线程池中执行异步任务
callbackExecutor.submit(() -> callback.onSuccess(result)); // 在回调线程池中执行成功回调
} catch (Exception e) {
callbackExecutor.submit(() -> callback.onFailure(e)); // 在回调线程池中执行失败回调
}
});
}
public void shutdown() {
try {
taskExecutor.shutdown();
callbackExecutor.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用示例:
public class AsyncDemo {
public static void main(String[] args) {
AsyncTaskExecutor executor = new AsyncTaskExecutor(10, 5);
Future<?> future = executor.executeAsync(() -> {
// 这是一个异步任务示例
Thread.sleep(1000); // 模拟耗时操作
return "任务结果";
}, new Callback<String>() {
@Override
public void onSuccess(String result) {
// 成功回调
System.out.println("异步任务成功完成,结果:" + result);
}
@Override
public void onFailure(Exception e) {
// 失败回调
System.out.println("异步任务执行失败");
e.printStackTrace();
}
});
// 根据需要取消任务
// 注意:取消正在执行的任务可能不会立即停止任务,且不是所有任务都可以取消
boolean cancelResult = future.cancel(true); // 参数true表示如果任务正在运行,应该被中断
if (cancelResult) {
System.out.println("任务已取消");
} else {
System.out.println("任务取消失败,可能已经完成或无法取消");
}
// 注意:在实际应用中,关闭线程池的操作应当放在应用关闭或者确定不再提交任何任务时进行
// executor.shutdown();
}
}
三、使用CompletableFuture
CompletableFuture是Java提供的异步回调工具,内部默认使用ForkJoinPool线程池。
使用示例:
CompletableFuture.supplyAsync(() -> {
// 异步执行的任务
return "异步结果";
}).thenAccept(result -> {
// 处理结果
System.out.println("异步任务的结果是: " + result);
}).exceptionally(e -> {
// 异常处理
e.printStackTrace();
return null;
});