自我成长 - java8
type: channel
link: https://www.yanxizhu.com/index.php/tag/java8/
items: JAVA8-Date and Time API： LocalDate, LocalTime, Instant, Duration, Period
items: AVA8-CompletableFuture常用API：runAfterBoth、applyToEither、acceptEither 、runAfterEither 、allOf、anyOf
items: JAVA8-CompletableFuture常用API：thenApply、handle、thenRun、thenAccept、thenCompose、thenCombine、thenAcceptBoth
items: JAVA8-CompletableFuture流水线工作，join多个异步任务详解
items: JAVA8-CompletableFuture基本用法
items: JAVA8-实现一个异步基于事件回调的Future程序
items: JAVA8-JDK自带Future,Callable,ExecutorService
items: JAVA8-多线程Future设计模式原理,自定义实现一个Future程序
items: JAVA8-default、static
items: JAVA8-自定义Spliterator

JAVA8-Date and Time API： LocalDate, LocalTime, Instant, Duration, Period
type: item
date: 2022-11-24T13:09:00+00:00
description: JAVA8-Date and Time API： LocalDate, LocalTime, Instant, Duration, Period旧API问题1、代码不清晰，一下看不出要转换的日期。2、Date日期中还包含了时间 3、多线程情况下会报错。代码重现：package com.example.study.java8.datetime; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateTest { public static void main(String[] args) throws ParseException { //122格林威治时间 11月 23日期 //问题：不能清晰表示日期 Date date = new Date(122, 11, 23); System.out.println(date); //多线程情况下会出现一些问题： //30个线程，每个线程下循环100次，执行时间格式转换。 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); for (int i = 0; i < 30; i++) { new Thread(() -> { for (int j = 0; j < 100; j++) { Date parseDate = null; try { parseDate = sdf.parse("20221123"); } catch (ParseException e) { e.printStackTrace(); } System.out.println(parseDate); } }).start(); } } }输出结果：Fri Dec 23 00:00:00 CST 2022 .。。。。。。。。。。 java.lang.NumberFormatException: For input string: "" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Long.parseLong(Long.java:702) at java.base/java.lang.Long.parseLong(Long.java:817) at java.base/java.text.DigitList.getLong(DigitList.java:195) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2121) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1931) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.example.study.java8.datetime.DateTest.lambda$main$0(DateTest.java:22) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "Thread-25" Exception in thread "Thread-14" java.lang.NumberFormatException: multiple points at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1914) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)新API学习1、LocalDate 线程安全package com.example.study.java8.datetime; import java.text.ParseException; import java.text.SimpleDateFormat; import java…

AVA8-CompletableFuture常用API：runAfterBoth、applyToEither、acceptEither 、runAfterEither 、allOf、anyOf
type: item
date: 2022-11-22T15:12:00+00:00
description: AVA8-CompletableFuture常用API：runAfterBoth、applyToEither、acceptEither 、runAfterEither 、allOf、anyOf1、runAfterBoth ：2个CompletableFuture都执行完后,再执行其它操作package com.example.study.java8.completableFutures.api; import java.util.concurrent.CompletableFuture; public class CompletableFutureAction2 { public static void main(String[] args) throws InterruptedException { //API-- 1、runAfterBoth: 2个都执行完后,再执行其它操作 CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "this is runing 1......"); return 1; }) .runAfterBoth(CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "this is runing 2......"); return 2; }), () -> System.out.println("done")); //为了防止主线程结束后，守护线程被关闭，模拟修改10000毫秒 Thread.sleep(10000); } }输出结果：ForkJoinPool.commonPool-worker-5this is runing 2...... ForkJoinPool.commonPool-worker-19this is runing 1...... done2、 applyToEither：其中一个CompletableFuture执行完，就将结果传给另一个Fuctionpackage com.example.study.java8.completableFutures.api; import java.util.concurrent.CompletableFuture; public class CompletableFutureAction2 { public static void main(String[] args) throws InterruptedException { //API-- 2、runAfterBoth: 其中一个CompletableFuture执行完，就将结果传递到另一个Function中。 CompletableFuture.supplyAsync(()->{ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"this is one future..."); return 1; }).applyToEither(CompletableFuture.supplyAsync(()->{ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"this is two future..."); return 2; }), v-> 10 * v ).thenAccept(System.out::println); //为了防止主线程结束后，守护线程被关闭，模拟修改10000毫秒 Thread.sleep(10000); } }输出结果：ForkJoinPool.commonPool-worker-5this is two future... 20 ForkJoinPool.commonPool-worker-19this is one future...3、acceptEither ：其中一个future执行完，就将结果传递到cutomer中消费package com.example.study.java8.completableFutures.api; import java.uti…

JAVA8-CompletableFuture常用API：thenApply、handle、thenRun、thenAccept、thenCompose、thenCombine、thenAcceptBoth
type: item
date: 2022-11-21T15:21:16+00:00
description: JAVA8-CompletableFuture常用API：thenApply、handle、thenRun、thenAccept、thenCompose、thenCombine、thenAcceptBoth1、thenApplypackage com.example.study.java8.completableFutures.api; import java.util.Optional; import java.util.concurrent.CompletableFuture; /** * CompletableFuture常用API: thenApply、handle */ public class CompletableFutureAtion1 { public static void main(String[] args) throws InterruptedException { //API-- 1、thenApply //模拟其它 异步 逻辑操作然后返回结果1 CompletableFuture.supplyAsync(() -> 1) .thenApply(i -> Integer.sum(i, 10)) //thenApply 将结果加10 .whenComplete((v, t) -> Optional.ofNullable(v).ifPresent(System.out::println)); //同步执行打印结果 // .whenCompleteAsync() //异步操作，可以将结果在进行其它逻辑异步操作 //whenComplete VS whenCompleteAsync //为了防止主线程结束后，守护线程被关闭，模拟修改10000毫秒 Thread.sleep(10000); } } 输出结果：11对比whenComplete VS whenCompleteAsync：whenCompleteAsync异步操作，可以将结果在进行其它逻辑异步操作。2、handlepackage com.example.study.java8.completableFutures.api; import java.util.Optional; import java.util.concurrent.CompletableFuture; /** * CompletableFuture常用API: thenApply、handle */ public class CompletableFutureAtion1 { public static void main(String[] args) throws InterruptedException { //API- 2、handle CompletableFuture.supplyAsync(() -> 1) .handle((v, t) -> Integer.sum(v, 10)) .whenComplete((v, t) -> Optional.ofNullable(v).ifPresent(System.out::println)); // thenApply VS handle :handle只是多了一个对堆内存的考虑。 //为了防止主线程结束后，守护线程被关闭，模拟修改10000毫秒 Thread.sleep(10000); } } 输出结果：11对比thenApply VS handle :handle只是多了一个对堆内存的考虑。3、thenRunpackage com.example.study.java8.completableFutures.api; import java.util.Optional; import java.util.concurrent.CompletableFuture; /** * CompletableFuture常用API: thenApply、handle */ public class CompletableFutureAtion1 { public static void main(String[] args) throws InterruptedException { //API-3、thenRun:所有结果执行完后，执行其它操作 CompletableFuture.supplyAsync(() -> 1) .handle((v, t) -> Integer.sum(v, 10)) .whenComplete((v, t) -> Optional.ofNullable(v).ifPresent(System.out::println)) .thenRun(System.out::println); //这里没有入参，…

JAVA8-CompletableFuture流水线工作，join多个异步任务详解
type: item
date: 2022-11-21T14:21:00+00:00
description: JAVA8-CompletableFuture流水线工作，join多个异步任务详解需求：根据商品id，将每个商品价格翻2倍？代码示例package com.example.study.java8.completableFutures; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; /** * 根据商品id，将每个商品价格翻2倍。CompletableFuture高并发执行。 */ public class CompletableFutureInAction4 { private final static Random RANDOM = new Random(System.currentTimeMillis()); public static void main(String[] args) { //防止主线程执行完后，守护线程也关闭 ExecutorService executorService = Executors.newFixedThreadPool(2, r -> { Thread thread = new Thread(r); thread.setDaemon(false); return thread; }); //5个商品ID List<Integer> productIDs = Arrays.asList(1, 2, 3, 4, 5); //通过CompletableFuture查询5个商品价格 Stream<CompletableFuture<Double>> completableFutureStream = productIDs.stream().map(i -> CompletableFuture.supplyAsync(() -> queryProduct(i), executorService)); //将每个商品价格翻2倍 Stream<CompletableFuture<Double>> multplyFutures = completableFutureStream.map(future -> future.thenApply(CompletableFutureInAction4::multply)); //将翻倍后的CompletableFuture加入线程中，将翻倍后价格收集成一个list数组 List<Double> result = multplyFutures.map(CompletableFuture::join).collect(toList()); //输出最后翻倍价格 System.out.println(result); } private static Double multply(Double value) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return value * 2D; } private static Double queryProduct(int i){ return CompletableFutureInAction4.get(); } //模拟从数据库根据商品ID查询价格 static double get(){ try { Thread.sleep(RANDOM.nextInt(100)); } catch (InterruptedException e) { e.printStackTrace(); } double value = RANDOM.nextDouble(); System.out.println(value); return value; } }输出结果：0.22471854337617791 0.11072895680534822 0.6087836739979867 0.3209858426806811 0.8416829454071859 [0.44943708675235583, 0.22145791361069644, 1.2175673479959734, 0.64197…

JAVA8-CompletableFuture基本用法
type: item
date: 2022-11-21T12:16:48+00:00
description: JAVA8-CompletableFuture基本用法针对<实现一个异步基于事件回调的Future程序> 用CompletableFuture进行改进。代码示例：package com.example.study.java8.completableFutures; import java.util.Optional; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; /** * CompletableFuture 基本用法 */ public class CompletableFutureInAction1 { private final static Random RANDOM = new Random(System.currentTimeMillis()); public static void main(String[] args) throws ExecutionException, InterruptedException { //实际开发中，一般不直接new，而是使用工厂创建 // CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(); CompletableFuture<Double> completableFuture = new CompletableFuture<>(); new Thread(()->{ double value = get(); completableFuture.complete(value); }).start(); //不会阻塞程序执行 System.out.println("===========no====block====.."); //1、后面获取程序执行结果 // Optional.ofNullable(completableFuture.get()).ifPresent(System.out::println); //2、执行完后，通过回调自动返回结果 completableFuture.whenComplete((v,t)->{ Optional.ofNullable(v).ifPresent(System.out::println); Optional.ofNullable(t).ifPresent(x->x.printStackTrace()); }); } private static double get(){ try { Thread.sleep(RANDOM.nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } return RANDOM.nextDouble(); } }输出结果：===========no====block====.. 0.5192854493861505

JAVA8-实现一个异步基于事件回调的Future程序
type: item
date: 2022-11-20T09:29:34+00:00
description: JAVA8-实现一个异步基于事件回调的Future程序前面2个例子（JAVA8-多线程Future设计模式原理,自定义实现一个Future程序、JAVA8-JDK自带Future,Callable,ExecutorService）+该例子，是为了学习CompletableFuture，理解其原理。自定义Future程序代码示例：package com.example.study.java8.funture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; /** * 实现一个异步基于事件回调的Future程序 */ public class FutureInAction3 { public static void main(String[] args) { Future<String> future = invoke(() -> { try { Thread.sleep(10000L); return "I'm finished."; } catch (InterruptedException e) { return "I'm Error."; } }); //注册一个事件 future.setCompletable(new Completable<String>() { @Override public void completable(String s) { System.out.println(s); } @Override public void excetion(Throwable cause) { System.out.println("Error"); cause.printStackTrace(); } }); //下面就可以执行其它逻辑了。。。 System.out.println("。。。。。。。。。"); System.out.println(future.get()); System.out.println(future.get()); } private static <T> Future<T> invoke(Callable<T> callable) { AtomicReference<T> result = new AtomicReference<>(); AtomicBoolean finished = new AtomicBoolean(false); Future future = new Future() { private Completable<T> completable; @Override public Object get() { return result.get(); } @Override public boolean isDone() { return finished.get(); } @Override public void setCompletable(Completable completable) { this.completable = completable; } @Override public Completable getCompletable() { return completable; } }; Thread t = new Thread(() -> { try { T value = callable.action(); result.set(value); finished.set(true); if (future.getCompletable() != null) { //调用回调函数 future.getCompletable().completable(value); } } catch (Exception cause) { if (future.getCompletable() != null) { future.getCompletable().excetion(cause); } } }); t.start(); return future; } /** * 自定义的Future * * @param <T> */ private interface Future<T> { T get(); boolean isDone(); void setCompletable(Completable<T> completable); Completable<T> getCompletable(); } private interface Callable<T> { T actio…

JAVA8-JDK自带Future,Callable,ExecutorService
type: item
date: 2022-11-20T08:31:37+00:00
description: JAVA8-JDK自带Future,Callable,ExecutorService代码示例：package com.example.study.java8.funture; import java.util.List; import java.util.concurrent.*; /** * 和自定义Future中block一样会卡住 */ public class FutureInAction2 { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { //创建一个单线程 ExecutorService executorService = Executors.newSingleThreadExecutor(); //返回一个future，里面的操作可能还没完成，但不影响后续的操作。 Future<String> future = executorService.submit(() -> { try { Thread.sleep(10000L); return "I'm finished"; } catch (InterruptedException e) { return "I'm error"; } }); //没有结果会抛出，中断异常 String value = future.get(); System.out.println(value); //关闭进程 executorService.shutdown(); //shutdownNow关闭进程，但是会返回有那些进程还没有执行完。 List<Runnable> runnables = executorService.shutdownNow(); } }输出结果：I'm finished //会阻塞等待操作计算完成，才输出结果。String value = future.get();也可以添加其它参数，设置等待时间，如果超过时间没返回值，就抛出异常。//最后等10秒没拿到，就抛出异常。 String value = future.get(10, TimeUnit.MICROSECONDS);代码示例：package com.example.study.java8.funture; import java.util.List; import java.util.concurrent.*; /** * 和自定义Future中block一样会卡住 */ public class FutureInAction2 { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { //创建一个单线程 ExecutorService executorService = Executors.newSingleThreadExecutor(); //返回一个future，里面的操作可能还没完成，但不影响后续的操作。 Future<String> future = executorService.submit(() -> { try { Thread.sleep(10000L); return "I'm finished"; } catch (InterruptedException e) { return "I'm error"; } }); //没有结果会抛出，中断异常 // String value = future.get(); //最后等10秒没拿到，就抛出异常。 String value = future.get(10, TimeUnit.MICROSECONDS); System.out.println(value); //关闭进程 executorService.shutdown(); //shutdownNow关闭进程，但是会返回有那些进程还没有执行完。 List<Runnable> runnables = executorService.shutdownNow(); } }抛出异常结果：Exception in thread "main" java.util.concurrent.TimeoutException at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)代码示例：package com.example.study.java8.funture; import java…

JAVA8-多线程Future设计模式原理,自定义实现一个Future程序
type: item
date: 2022-11-20T07:27:15+00:00
description: JAVA8-多线程Future设计模式原理,自定义实现一个Future程序。自定义实现Future，理解设计模式原理。Future模式实现自定义代码示例：package com.example.study.java8.funture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; /** * 自定义模拟future，理解Future的使用。 */ public class FutureInAction { public static void main(String[] args) throws InterruptedException { Funture<String> funture = invoke(() -> { try { //模拟操作计算很长时间 Thread.sleep(10000); return "I'm finished"; } catch (Exception e) { e.printStackTrace(); return "Error"; } }); //操作计算很长时间，还没操作计算完成，只返回了future，虽然此时返回值为null，但是可以接着执行官其它操作,不会阻塞后续操作。 System.out.println(funture.get()); System.out.println(funture.get()); System.out.println(funture.get()); //知道操作计算完成后，将值返回 while (!funture.isDone()) { Thread.sleep(10); } System.out.println(funture.get()); } private static <T> Funture<T> invoke(Callable<T> callable) { AtomicReference<T> result = new AtomicReference<>(); AtomicBoolean finished = new AtomicBoolean(false); Thread t = new Thread(() -> { T value = callable.action(); result.set(value); finished.set(true); }); t.start(); Funture funture = new Funture() { @Override public Object get() { return result.get(); } @Override public boolean isDone() { return finished.get(); } }; return funture; } private interface Funture<T> { T get(); boolean isDone(); } private interface Callable<T> { T action(); } }输出结果：null //这里没有阻塞 null //这里没有阻塞 null //这里没有阻塞 I'm finished //这里没有阻塞null之前没有阻塞，可以之前后续的其它操作。用没有使用Future的方式实现package com.example.study.java8.funture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; /** * 自定义模拟future，理解Future的使用。 */ public class FutureInAction { public static void main(String[] args) throws InterruptedException { //以前没有future，阻塞方式测试 String str = block(() -> { try { //模拟操作计算很长时间 Thread.sleep(10000); return "I'm finished"; } catch (Exception e) { e.printStackTrace(); return "Error"; } }); //这里就会阻塞等返回结果，再执行下面的其他操作。 System.out.println(str); } //最早的没有future，实现方式 private stati…

JAVA8-default、static
type: item
date: 2022-11-19T10:18:17+00:00
description: JAVA8-default、staticdefault方法1.8之前出现的问题:开发了一个接口，后面实现该接口的实现类，都需要实现接口中定义的方法。1.8之后接口中使用default定义新增的方法后，其实现类可以不用实现该方法。例如Collection接口中新增了对stream的操作方法：stream()public interface Collection<E> extends Iterable<E> { default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } }其实现类就可以不用再实现stream()方法，这样对于版本兼容就比较好了。static 定义的方法可以通过接口直接调用该方法，例如：public interface Function<T, R> { static <T> Function<T, T> identity() { return t -> t; } }注意：接口中有default定义的方法实现了，但并不是抽象类。接口：可以被多个类实现。抽象类：继承了一个抽象类，就不能再继承另一个抽象类，因为类是单继承。实列自己用default实现一个接口package com.example.study.java8.method; /** * default使用 */ public class DefaultAction { public static void main(String[] args) { A a = ()->10; System.out.println(a.size()); System.out.println(a.isEmpty()); } public interface A{ int size(); //判断容器是否为空 default boolean isEmpty(){ return size()==0; } } }输出结果：10 false问题思考：当接口中定义default方法后，被多个类实现会不会出现冲突？问题思考，代码示例：package com.example.study.java8.method; public class DefaultActon2 { public void confuse(Object obj){ System.out.println("Object"); } public void confuse(int[] i){ System.out.println("int[]"); } public static void main(String[] args) { DefaultActon2 action = new DefaultActon2(); action.confuse(null); int [] arr = null; Object obj = arr; action.confuse(obj); } }输出结果：int[] Object思考：为什么传null，就是调用的int[]数组的方法，而下面的数组指向Object后，调用的时第一个object方法？因为当传null的时候，会调用声明更具体的方法，如上面的int[] i，明确定义了是一个int数组，而Object不是特别具体。Default方法解决多重继承冲突的三大原则1、类的优先级最高2、上一级接口，不管上一级接口有多少个类3、如果混淆了，就必须重写。类的优先级最高，示例：package com.example.study.java8.method; /** * 1、类的优先级最高 * 2、上一级接口，不管上一级接口有多少个类 */ public class DefaultAction3 { public static void main(String[] args) { A c = new C(); c.hello(); } public interface A{ default void hello(){ System.out.println("A-Hello"); } } public interface B extends A{ @Override default void hello(){ System.out.println("B-Hello"); } } public static class C implements B , A{ @Override public void hello() { System.out.println("C-Hello"); } } }输出结果：C-Hello混淆了，就必须重写，示例：package com.example.study.java8…

JAVA8-自定义Spliterator
type: item
date: 2022-09-21T13:12:05+00:00
description: JAVA8-自定义Spliterator需求说明：将一段话按换行符分割成多个执行，并输出。package com.example.study.java8.forkjoin; import java.util.Objects; import java.util.Spliterator; import java.util.function.Consumer; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * 自定义Spliterator * 实列：将一段话按换行符分割成多个执行，并输出。 */ public class SpliteratorInAction { //需要处理的数据 private static String text = "The tryAdvance method feeds the Consumer with the Character in the String at the current index\n" + "position and increments this position. The Consumer passed as argument is an internal Java class\n" + "forwarding the consumed Character to the set of functions that have to be applied to it while\n" + "traversing the stream, which in this case is only a reducing function, namely, the accumulate method\n" + "of the WordCounter class. The tryAdvance method returns true if the new cursor position is less\n" + "than the total String length and there are further Characters to be iterated.\n" + "\uF0B7 The trySplit method is the most important one in a Spliterator because it’s the one defining the\n" + "logic used to split the data structure to be iterated. As you did in the compute method of the\n" + "RecursiveTask implemented in listing 7.1 (on how to use the fork/join framework), the first thing\n" + "you have to do here is set a limit under which you don’t want to perform further splits. Here, you use a\n" + "very low limit of 10 Characters only to make sure that your program will perform some splits with\n" + "the relatively short String you’re parsing, but in real-world applications you’ll have to use a higher\n" + "limit, as you did in the fork/join example, to avoid creating too many tasks. If the number of\n" + "remaining Characters to be traversed is under this limit, you return null to signal that no further\n" + "split is necessary. Conversely, if you need to perform a split, you set the candidate split position to the\n" + "half of the String chunk remaining to be parsed. But you don’t use t…