文章目录
- 1 Future接口
- 1.1 FutureTask相关接口关系
- 1.2 Future接口的优缺点
- 1.2.1 优点
- 1.2.2 缺点
- 2 Complatable Future
- 2.1 CompletionStage
- 2.2 使用案例
- 2.2.1 runAsync
- 2.2.2 supplyAsync
- 2.2.3 join和get的区别
- 2.2.4 CF simple project使用案例
- 2.2.5 CF 常用API
- 2.2.5.1 获取结果和主动触发计算
- 2.2.5.2 对计算结果进行处理
- 2.2.5.3 对计算结果进行消费
- 2.2.5.4 对计算速度进行选用
1 Future接口
1.1 FutureTask相关接口关系
1.2 Future接口的优缺点
1.2.1 优点
结合线程池,可以提升程序的运算效率。
1.2.2 缺点
(1) get方法阻塞
(2)isDone通常会轮询
我们还想需要:
(1) 缺少完成时的回调通知。
(2) 多个任务前后依赖可以组合处理。
(3)选择计算速度最快的那个线程。
2 Complatable Future
2.1 CompletionStage
2.2 使用案例
2.2.1 runAsync
2.2.2 supplyAsync
package org.example.completablefuturetest;
import java.util.concurrent.*;
public class CompletableFutureUseDemo {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
try {
CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + "-------come in.");
int result = ThreadLocalRandom.current().nextInt(10);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("---------2s之后出结果---" + result);
if (result > 2) {
throw new RuntimeException("sk, throw a run time exception.");
}
return result;
}, threadPool).whenComplete((value, exception) -> {
if (exception == null) {
System.out.println("-------计算完成,更新系统value:---" + value);
}
}).exceptionally(exception -> {
System.out.println("sk, will handle a ex.");
exception.printStackTrace();
return null;
});
System.out.println(Thread.currentThread().getName() + "线程先去忙其他任务");
} catch (Exception exception) {
exception.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
2.2.3 join和get的区别
就是抛出的异常不一样。 join不需要使用方显示地捕获异常。
public class CompletableFutureMallDemo {
public static void main(String[] args) {
CompletableFuture cf = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "sk, 1234";
}
});
System.out.println(cf.join());
}
}
2.2.4 CF simple project使用案例
package org.example.cfmall;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class CompletableFutureMallDemo {
static List<NetMall> list = Arrays.asList(
new NetMall("jingdong"),
new NetMall("dangdang"),
new NetMall("taobao")
);
public static List<String> getPrice(List<NetMall> list, String productName) {
// return getPriceStepByStep(list, productName);
return getPriceAsync(list, productName);
}
private static List<String> getPriceAsync(List<NetMall> list, String productName) {
return list.stream().map(netMall -> CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return String.format(productName + "in %s price is %.2f",
netMall.getNetMallName(), netMall.calcPrice(productName));
}
})).collect(Collectors.toList()).stream().map(cf -> cf.join()).collect(Collectors.toList());
}
private static List<String> getPriceStepByStep(List<NetMall> list, String productName) {
return list.stream().map(netMall -> String.format(productName + "in %s price is %.2f",
netMall.getNetMallName(), netMall.calcPrice(productName))).collect(Collectors.toList());
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<String> priceList = getPrice(list, "mysql");
for (String price : priceList) {
System.out.println(price);
}
long endTime = System.currentTimeMillis();
System.out.println("------costTime: " + (endTime - startTime) + " ms");
}
}
@AllArgsConstructor
@NoArgsConstructor
@Data
class NetMall {
private String netMallName;
public double calcPrice(String productName) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
}
}
2.2.5 CF 常用API
2.2.5.1 获取结果和主动触发计算
2.2.5.2 对计算结果进行处理
2.2.5.3 对计算结果进行消费
带Async后缀和不带后缀的api的区别