文章目录
前言
做一个高并发学习过程的笔记记录 之前断断续续的一直有在学 在看书但是一直没有整理 现在想统一串一下 在这块做一个零散的笔记看看效果如何
一些基础概念
函数式接口示意图
管程
其实他就是咱们常说的锁 它是由操作系统保证的一种同步机制.os中称之为 Monitor(监视器). jvm的同步就是基于进入和退出monitor来实现的,每个对象都会有一个monitor对象
守护线程与用户线程
守护线程即daemon为true设置的线程 他将跟随主线程的消亡而关闭(比如垃圾回收等线程都为守护线程)
用户线程就是daemon为false的设置 默认就为false所以平时咱们自己建立的都是用户线程 用户和主线程互不干扰单独执行
牢记一点 设置守护线程 必须放到start方法之前
FutureTask
让子线程去执行任务 等过段时间 用get方法再去获取任务结果(get获取结果是阻塞的 所以实在要用的话建议放到最后) 工作中get禁用的 必须用 futureTask.get(2, TimeUnit.SECONDS) 带超时时间的方法
高并发就是要克服阻塞,尽量少加锁,怎么克服阻塞呢?尽量用轮询替代阻塞 但是轮询也是阻塞的一种
CompletableFuture
java8对 FutureTask 的加强和扩展 他实现了 Future和CompletionStage 接口 是使用线程池去执行线程的 如果你没有创建指定 就会用默认的 ForkJoinPool.commonPool() 线程池
一般是采用有返回值的 supplyAsync方法 join和get方法获取结果会阻塞,但是join方法不抛出异常
所有带Async的方法 是把方法的执行提交给线程池去做的 不带Async就是由当前的线程进行执行,所以基本不用Async的方法会造成多的一次线程上下文的切换消耗 但是CompletableFuture会随着主线程的销毁而销毁 不会再继续执行
"多箭齐发"的示例代码(在循环流中的并发执行):
public class CompleteFutureNetMallDemo {
static List<NetMall> list = Arrays.asList(
new NetMall("jd"), new NetMall("pdd"), new NetMall("tm"));
public static List<String> getPriceByStep(List<NetMall> list, String productName) {
return list.parallelStream().map(netMall -> String.format(productName + "in %s price is %.2f", netMall.getMallName(), netMall.getPrice(productName))).collect(Collectors.toList());
}
public static List<String> getPriceByASync(List<NetMall> list, String productName) {
return list.stream().map(netMall -> CompletableFuture.supplyAsync(() ->
String.format(productName + "in %s price is %.2f", netMall.getMallName(), netMall.getPrice(productName))))
.collect(Collectors.toList()).stream().map(CompletableFuture::join).collect(Collectors.toList());
}
public static void main(String[] args) {
System.out.println(getPriceByASync(list,"aa"));
}
}
class NetMall {
private String mallName;
public NetMall(String mallName) {
this.mallName = mallName;
}
public double getPrice(String productName) {
try {
TimeUnit.SECONDS.sleep(1L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
}
public String getMallName() {
return mallName;
}
public void setMallName(String mallName) {
this.mallName = mallName;
}
}
计算结果谁快用谁(慢的也会执行完成):
System.out.println(CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return 2;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(333);
return 3;
}), r -> {
return r;
}).join());
try {
TimeUnit.SECONDS.sleep(5L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
多个计算结果的合并
适用于调用多个三方接口 或者聚合微服务的数据
System.out.println(CompletableFuture.supplyAsync(() -> {
return 10;
}).thenCombine(CompletableFuture.supplyAsync(() -> {
return 20;
}), Integer::sum).join());