JUC第二天总结
get 和 join的区别
get和join一样的都会造成线程堵塞,区别就是join不抛出异常。
CompletableFutrue的应用
public class CompletableFutureDemo01 {
/**CompletableFuture应用
* 需求:
* 同一款产品,同时搜索出同款产品在不同平台的售价
* 同一款产品,同时搜索出同款产品在同一个平台的各个商家的售价
* 技术:
* stream流式计算,函数式编程,链式编程
*/
//定义一个静态数组
static List<Product> list = Arrays.asList(
new Product("pdd"),
new Product("taobao"),
new Product("tmall"),
new Product("jd")
);
//同步 step by step
public static List<String> productStep(List<Product> list ,String productPriceName){
return list.stream()
.map(product -> String.format(productPriceName+" in %s price is %.2f",
product.getProductName(),product.getProductPrice(productPriceName)))
.collect(Collectors.toList());
}
//异步 万剑齐发
public static List<String> productAsynt(List<Product> list ,String productPriceName){
return list.stream()
.map(product -> CompletableFuture.supplyAsync(() ->
String.format(productPriceName+" in %s price is %.2f",product.getProductName()
,product.getProductPrice(productPriceName))))
.collect(Collectors.toList())
.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<String> list = productStep(CompletableFutureDemo01.list, "mysql");
for (String s : list) {
System.out.println(s);
}
long endTime = System.currentTimeMillis();
System.out.println("耗时:"+(endTime - startTime)+"s");
long startTime1 = System.currentTimeMillis();
List<String> list1 = productAsynt(CompletableFutureDemo01.list, "mysql");
for (String s : list1) {
System.out.println(s);
}
long endTime1 = System.currentTimeMillis();
System.out.println("耗时:"+(endTime1 - startTime1)+"s");
}
}
class Product{
@Getter
private String productName;
public Product(String productName) {
this.productName = productName;
}
public double getProductPrice(String productPriceName){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ThreadLocalRandom.current().nextDouble()*2 + productPriceName.charAt(0);
}
}
运行结果:
mysql in pdd price is 110.24
mysql in taobao price is 110.18
mysql in tmall price is 109.90
mysql in jd price is 110.74
耗时:4173s
mysql in pdd price is 109.79
mysql in taobao price is 109.35
mysql in tmall price is 109.43
mysql in jd price is 110.92
耗时:1022s
由此看出同步与异步执行结果的差别了吧。
CompletableFuture常用方法
获取结果和触发计算
获取结果:
==public T get() ==:不见不散
不管让程序休眠多长时间,只要返回我就接受
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 147;
});
System.out.println(exceptionally.get());
// TimeUnit.SECONDS.sleep(5);
threadPoolExecutor.shutdown();
==public T get(long timeout, TimeUnit unit) ==:过时不候
设置一个等待时间要是在规定时间类获取到值,则输出
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 147;
});
System.out.println(exceptionally.get(2,TimeUnit.SECONDS));
// TimeUnit.SECONDS.sleep(5);
threadPoolExecutor.shutdown();
public T getNow(T valueIfAbsent):没有计算完成的情况下给我一个替代结果,也就是立即获取结果不阻塞,计算完返回计算完成后的结果,没有计算完则返回valueIfAbsent的值
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 147;
});
//TimeUnit.SECONDS.sleep(2);
System.out.println(exceptionally.getNow(520));
threadPoolExecutor.shutdown();
public T join()
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
System.out.println(CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 147;
}).join());
//TimeUnit.SECONDS.sleep(2);
threadPoolExecutor.shutdown();
==public boolean complete(T value) ==:是否立即打断get()返回括号值
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 147;
});
//当调用CompletableFuture.get()被阻塞的时候,complete方法就是结束阻塞并get()获取设置的complete里面的值.
System.out.println(exceptionally.complete(520) + "\t" + exceptionally.get());
threadPoolExecutor.shutdown()
对结算结果进行处理
thenApply:
计算结果存在依赖关系,这两个线程串行化;由于存在依赖关系(当前步错,不走下一步),当前步骤有异常的话就叫停。
//当一个线程依赖另一个线程时用 thenApply 方法来把这两个线程串行化,
CompletableFuture.supplyAsync(() -> {
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("111");
return 1024;
}).thenApply(f -> {
System.out.println("222");
return f + 1;
}).thenApply(f -> {
//int age = 10/0; // 异常情况:那步出错就停在那步。
System.out.println("333");
return f + 1;
}).whenCompleteAsync((v,e) -> {
System.out.println("*****v: "+v);
}).exceptionally(e -> {
e.printStackTrace();
return null;
});
System.out.println("-----主线程结束,END");
// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
}
handle:有异常也可以往下一步走,根据带的异常参数可以进一步处理
//当一个线程依赖另一个线程时用 handle 方法来把这两个线程串行化,
// 异常情况:有异常也可以往下一步走,根据带的异常参数可以进一步处理
CompletableFuture.supplyAsync(() -> {
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("111");
return 1024;
}).handle((f,e) -> {
int age = 10/0;
System.out.println("222");
return f + 1;
}).handle((f,e) -> {
System.out.println("333");
return f + 1;
}).whenCompleteAsync((v,e) -> {
System.out.println("*****v: "+v);
}).exceptionally(e -> {
e.printStackTrace();
return null;
});
System.out.println("-----主线程结束,END");
// 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
}
whencomplete和whencompleteAsync的区别
whencomplete:是执行当前任务的线程执行继续执行whencomplete的任务
whencompleteAsync:是执行把whencompleteAsync这个任务继续提交给线程池来进行执行
对计算结果进行消费
thenApply
CompletableFuture.supplyAsync(() -> {
return 1;
}).thenApply(f -> {
return f + 2;
}).thenApply(f -> {
return f + 3;
}).thenApply(f -> {
return f + 4;
}).thenAccept(r -> System.out.println(r));
补充 :Code之任务之间的顺序执行
thenRun(Runnable runnable)
任务 A 执行完执行 B,并且 B 不需要 A 的结果
thenAccept(Consumer action)
任务 A 执行完执行 B,B 需要 A 的结果,但是任务 B 无返回值
thenApply(Function fn)
任务 A 执行完执行 B,B 需要 A 的结果,同时任务 B 有返回值
对计算速度进行选用
applyToEither
谁快用谁
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
System.out.println(CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 2;
}), r -> {
return r;
}).join());
TimeUnit.SECONDS.sleep(3);
threadPoolExecutor.shutdown();
对计算结果进行合并
thenCombine
两个CompletionStage任务都完成后,最终能把两个任务的结果一起交给thenCombine 来处理
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
System.out.println(CompletableFuture.supplyAsync(() -> {
return 10;
}).thenCombine(CompletableFuture.supplyAsync(() ->{
return 12;
}),(r1,r2) ->{
return r1+r2;
}).thenCombine(CompletableFuture.supplyAsync(() ->{
return 20;
}),(r1,r2) ->{
return r1+r2;
}).join());
TimeUnit.SECONDS.sleep(3);
threadPoolExecutor.shutdown();