一、什么是Future?
在并发编程中,可以通过Future对象来异步获取结果。
使用Thread或runnable接口都不能获取异步的执行结果,因为他们没有返回值。而通过实现Callable接口和Future就可以获取异步执行的结果,当异步执行结束后,返回结果将保存在Future中。使用Future就可以让我们暂时去处理其他的任务而无需一直等待结果,等异步任务执行完毕再返回其结果。
二、Future中的get方法
1、get方法
获取任务结束后返回的结果,如果调用时,任务还没有结束,则会进行阻塞线程,直到任务完成。该阻塞是可以被打断的,打断的线程是调用get方法的线程,被打断后原任务会依旧继续执行。
V get() throws InterruptedException, ExecutionException;
2、指定时间的get方法
获取任务结束后返回的结果,如果调用时,任务还没有结束,则会进行阻塞线程,等待一定时间,如果在规定时间内任务结束则返回结果,否则抛出TimeoutException,超时后任务依旧会继续执行。该阻塞是可以被打断的,打断的线程是调用get方法的线程,被打断后原任务会依旧继续执行。
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
三、Future代码示例
步骤1:创建一个线程池
public class AsyncTaskExecutor {
/**
* 核心线程数
*/
private static final int corePoolSize = 10;
/**
* 最大线程数
*/
private static final int maxPoolSize = 30;
/**
* 空闲线程回收时间
* 空闲线程是指:当前线程池中超过了核心线程数之后,多余的空闲线程的数量
*/
private static final int keepAliveTime = 100;
/**
* 任务队列/阻塞队列
*/
private static final int blockingQueueSize = 99999;
private static final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(blockingQueueSize),
new ThreadFactoryBuilder().setNameFormat("AsyncTaskThread" + "-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
/**
* 异步任务执行
*
* @param task
*/
public static void execute(Runnable task) {
executorPool.execute(task);
}
/**
* 异步执行任务Callable, 通过Future获取结果
*
* @param task
* @param <T>
* @return
*/
public static <T> Future<T> submit(Callable<T> task) {
return executorPool.submit(task);
}
/**
* 异步执行任务Runnable,通过Future获取结果
*
* @param task
* @return
*/
public static Future<?> submit(Runnable task) {
return executorPool.submit(task);
}
}
步骤2:编写测试类
@Test
public void test2() {
try {
Future<String> future = AsyncTaskExecutor.submit(() -> {
log.info("[Future Task] future task start...");
try {
//模拟任务执行
Thread.sleep(5000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
log.info("[Future Task] future task end...");
return "Task completed...";
});
//执行其他任务
log.info("[Main Thread] main thread is running...");
//使用future阻塞等待任务完成,并获取结果
String futureResult = future.get();
log.info("[Main Thread] {}", futureResult);
}catch (Exception e) {
e.printStackTrace();
}
}
步骤3:查看结果
2024-05-28 10:58:23.633 INFO 1184 --- [ main] com.example.demo.dao.UserDaoTest : [Main Thread] main thread is running...
2024-05-28 10:58:23.633 INFO 1184 --- [yncTaskThread-0] com.example.demo.dao.UserDaoTest : [Future Task] future task start...
2024-05-28 10:58:28.633 INFO 1184 --- [yncTaskThread-0] com.example.demo.dao.UserDaoTest : [Future Task] future task end...
2024-05-28 10:58:28.634 INFO 1184 --- [ main] com.example.demo.dao.UserDaoTest : [Main Thread] Task completed...
四、ListenableFuture
public class AsyncTaskExecutor {
/**
* 核心线程数
*/
private static final int corePoolSize = 10;
/**
* 最大线程数
*/
private static final int maxPoolSize = 30;
/**
* 空闲线程回收时间
* 空闲线程是指:当前线程池中超过了核心线程数之后,多余的空闲线程的数量
*/
private static final int keepAliveTime = 100;
/**
* 任务队列/阻塞队列
*/
private static final int blockingQueueSize = 99999;
private static final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(blockingQueueSize),
new ThreadFactoryBuilder().setNameFormat("AsyncTaskThread" + "-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
/**
* 创建一个ListeningExecutorService,用于执行异步任务
* (通过submit提交任务,以ListenableFuture获取结果)
*/
private static final ListeningExecutorService LISTENING_EXECUTOR = MoreExecutors.listeningDecorator(executorPool);
/**
* 异步任务执行
*
* @param task
*/
public static void execute(Runnable task) {
executorPool.execute(task);
}
/**
* 异步执行任务Callable, 通过ListenableFuture获取结果
*
* @param task
* @param <T>
* @return
*/
public static <T> ListenableFuture<T> submit(Callable<T> task) {
return LISTENING_EXECUTOR.submit(task);
}
/**
* 异步执行任务Runnable,通过Future获取结果
*
* @param task
* @return
*/
public static ListenableFuture<?> submit(Runnable task) {
return LISTENING_EXECUTOR.submit(task);
}
}
//示例1:
@Test
public void test2() {
ListenableFuture<School> listenableFuture1 = AsyncTaskExecutor.submit(() -> {
try {
//模拟任务执行
Thread.sleep(2000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
return new School("DSchool");
});
ListenableFuture<School> listenableFuture2 = AsyncTaskExecutor.submit(() -> {
try {
//模拟任务执行
Thread.sleep(3000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
return new School("ESchool");
});
//阻塞等待,直到listenableFuture1 和 listenableFuture2都获取到结果后或其中一个异常
Futures.successfulAsList(listenableFuture1, listenableFuture2).get();
School resSchool1 = listenableFuture1.get();
School resSchool2 = listenableFuture2.get();
log.info("[Main Thread] result1 is {}", JSON.toJSONString(resSchool1));
log.info("[Main Thread] result2 is {}", JSON.toJSONString(resSchool2));
//任意位置即时设定ListenableFuture的返回结果
ListenableFuture<School> listenableFuture3 = Futures.immediateFuture(new School("aaa"));
ListenableFuture<School> listenableFuture4 = Futures.immediateFailedFuture(new Exception("eeee"));
log.info("[Main Thread] listenableFuture3 is {}", listenableFuture3.get());
log.info("[Main Thread] listenableFuture4 is {}", listenableFuture4.get());
}catch (Exception e) {
e.printStackTrace();
}
}
//示例2:
public static void main(String[] args) {
// 创建一个ListeningExecutorService,用于执行异步任务
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
// 提交一个异步任务,并得到ListenableFuture对象
ListenableFuture<String> listenableFuture = executor.submit(() -> {
// 模拟耗时操作
Thread.sleep(2000);
return "Result of the asynchronous computation";
});
// 注册异步操作完成时的回调函数
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("Result: " + result);
executor.shutdown(); // 关闭executor
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
executor.shutdown(); // 关闭executor
}
}, executor);
}
五、CompletableFuture
//示例1:
public static void main(String[] args) {
// 创建一个CompletableFuture对象
CompletableFuture<School> completableFuture = new CompletableFuture<>();
// 异步任务:模拟一个耗时操作
new Thread(() -> {
try {
// 模拟耗时操作
Thread.sleep(2000);
// 完成CompletableFuture并设置值
completableFuture.complete(new School("completableSchool"));
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 在这里等待异步任务的结果并输出
try {
School result = completableFuture.get();
log.info("[CompletableFuture] result is {}" ,result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
//示例2:
@Test
public void test2() {
try {
//创建一个CompletableFuture对象
CompletableFuture<School> schoolFuture = new CompletableFuture<>();
//任意位置即时设定CompletableFuture的返回结果
schoolFuture.complete(new School("FSchool"));
School school = schoolFuture.get();
log.info("[Main Thread] result is {}", JSON.toJSONString(school));
}catch (Exception e) {
log.info(e.getMessage());
}
}
六、SettableFuture
//示例1:
public static void main(String[] args) {
// 创建一个SettableFuture对象
SettableFuture<String> settableFuture = SettableFuture.create();
// 手动设置异步操作的结果
settableFuture.set("Result of the asynchronous computation");
// 注册异步操作完成时的回调函数
settableFuture.addListener(() -> {
try {
String result = settableFuture.get(); // 获取异步操作的结果
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}, Runnable::run);
}
//示例2:
@Test
public void test2() {
try {
//创建一个SettableFuture对象
SettableFuture<School> settableFuture = SettableFuture.create();
//任意位置即时设定SettableFuture的返回结果
settableFuture.set(new School("GSchool"));
School setSchool = settableFuture.get();
log.info("[Main Thread] setSchool is {}", JSON.toJSONString(setSchool));
}catch (Exception e) {
log.info(e.getMessage());
}
}