JDK8-11-CompletableFuture(4)- supplyAsync 方法使用
生活中有一些多线程的例子,例如顾客去餐馆点餐,大致可以分为如下几个步骤:
1.顾客进入餐厅
2.顾客开始点餐
3.厨师按照顾客所选菜品开始炒菜
4.厨师打饭(假设没有服务员)
5.顾客开始吃饭
其中,在厨师准备饭菜的3,4步骤中,顾客处于等待状态,可以做些其他事情,比如玩手机,下面用程序模拟这个案例:
工具类,用于模拟耗时和打印当前时间戳和线程信息
import java.util.StringJoiner;
public class PrintTool {
public static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void printTimeAndThread(String str) {
String result = new StringJoiner("\t|\t")
.add(String.valueOf(System.currentTimeMillis()))
.add(String.valueOf(Thread.currentThread().getId()))
.add(Thread.currentThread().getName())
.add(str)
.toString();
System.out.println(result);
}
}
使用 supplyAsync 开启异步任务的例子:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class SupplyAsyncTest01 {
public static void main(String[] args) {
PrintTool.printTimeAndThread("顾客进入餐厅。。。");
PrintTool.printTimeAndThread("顾客开始点餐。。。");
CompletableFuture<String> cf = CompletableFuture.supplyAsync(()->{
PrintTool.printTimeAndThread("厨师开始炒菜。。。");
PrintTool.sleep(500);
PrintTool.printTimeAndThread("厨师开始打饭。。。");
PrintTool.sleep(200);
return "番茄炒蛋+米饭";
});
PrintTool.printTimeAndThread("顾客玩手机中。。。");
try {
PrintTool.printTimeAndThread(String.format("顾客开始吃%s",cf.get()));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
程序执行结果:
1665891657796 | 1 | main | 顾客进入餐厅。。。
1665891657798 | 1 | main | 顾客开始点餐。。。
1665891660537 | 1 | main | 顾客玩手机中。。。
1665891660537 | 14 | ForkJoinPool.commonPool-worker-1 | 厨师开始炒菜。。。
1665891661044 | 14 | ForkJoinPool.commonPool-worker-1 | 厨师开始打饭。。。
1665891661274 | 1 | main | 顾客开始吃番茄炒蛋+米饭
从执行结果中可以看出,main线程处理顾客相关动作,ForkJoinPool.commonPool-worker-1 线程处理厨师相关动作,从时间戳可以看出顾客玩手机和厨师开始炒菜都是1665891660537 ,符合异步处理场景
分析
supplyAsync 是 CompletableFuture 类静态方法,包括有无线程池入参两个重载方法
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
其中入参 Supplier(翻译为:供应商) 为 函数式接口(有且仅有一个抽象方法)
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
如果不传入Executor 入参则默认使用 ForkJoinPool 线程池创建异步任务