java8

********************************************************************************

java8编程知识,流式特性可参考http://www.php.cn/java-article-353260.html

********************************************************************************

 

java8中Map新增了一个computeIfAbsent()方法,判断是否存在key,若存在则返回value,否则则执行函数

// Map.computeIfAbsent(key,Function<T,R>)
public static Long getLong(Integer integer) { Map<Integer, Long> map = Maps.newHashMap(); long f = map.computeIfAbsent(integer, p -> { Integer result = p * 2; return result.longValue(); }); return f; }

 

多线程:CompletableFuture,使用多线程时需要格外注意细节,否则容易造成系统业务混乱!使用并行流时并行数与系统的内核数量一致,线程数默认也与内核数一致,而线程数可以通过设置线程池来确定,不过线程池的数量要适合否则容易容易导致效率更低。

——不使用工厂方法创建CompletableFuture

public CompletableFuture<String> completableFuture() {
    CompletableFuture<String> future = new CompletableFuture<>();
    new Thread(() -> {
        System.out.println("请开始你的表演...");
        try {
            Thread.sleep(1000L);
       // 接受返回值 future.complete("hello World"); } catch (InterruptedException e) { e.printStackTrace();
       // 捕捉线程中抛出的异常,会抛到调用者 future.completeExceptionally(e); } })
  // 必须启动线程,否则future无法储存返回值
  .start(); return future; }
// 立即返回future,不会被阻塞(等待线程执行结束)
CompletableFuture<String> future = completableFuture();
// join与get方法的目的一样,区别在于空值时get会抛出异常而join则会返回null,此时会阻塞 System.out.println(future.join());
// 输出:
请开始你的表演...

      hello World


 

——使用工厂类创建CompletableFuture对象,supplyAsync方法接收Supplier(提供者接口),并保存返回值

public CompletableFuture<String> completableFuture(String hello) {
    return CompletableFuture.supplyAsync(() -> hello);
}

 

——thenCompose线程依赖性:线程B的执行需要线程A的结果值,其中B是同步执行,被阻塞

@Test
public void compose() {
   // thenCompose方法接收Function参数,线程A的结果值以value形参传入B线程并返回一个CompletableFuture对象,对象中保存hello World结果值 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "hello").thenCompose(value -> CompletableFuture.supplyAsync(() -> value + " World")); String result = future.join(); System.out.println("result = " + result); }
// 输出:result = hello World

 

——thenCombine线程合并:线程A和线程B都执行结束后,各自返回一个值,使用BiFunction接口接收这两个结果并进行操作,A,B线程异步执行,B线程不会被阻塞

@Test
public void compose() {
  // thenCombine接收CompletionStage和BiFunction参数,两个线程同时执行并返回v1,v2 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "hello").thenCombine(CompletableFuture.supplyAsync(() -> " world"), (v1, v2) -> v1 + v2); String result = future.join(); System.out.println("result = " + result); }
// 输出:result = hello world

 

流与线程的结合 

@Test
public void stream() {
    List<test.VcUser> list = Arrays.asList(
            new VcUser("demo1"),
            new VcUser("demo2"),
            new VcUser("demo3")
    );
    // 自定义线程池,设定线程数量与集合长度取最小值,设定的线程数量并非越多越好,够用就行
    final Executor executor = Executors.newFixedThreadPool(Math.min(list.size(), 10), runnable -> {
        Thread thread = new Thread(runnable);
        // 新建一个守护线程,防止 一个线程异常导致其他线程无法执行
        thread.setDaemon(true);
        return thread;
    });
    
    // 将集合通过流转化为用线程来处理数据(将同步转化为异步),提高执行效率,executor为自定义的线程池,注意!!!这里创建线程的时候并没有把函数执行完(只执行一部分),因此需要再次执行join或者get方法方可真正执行线程,千万别忘了
  List<CompletableFuture<String>> futureList = list.stream().map(user -> CompletableFuture.supplyAsync(user::getName, executor)).collect(Collectors.toList()); 
  List<String> stringList =
futureList.stream().map(CompletableFuture::join).collect(Collectors.toList()); stringList.forEach(System.out::println); }
// 输出:demo1
     demo2
     demo3

 

注意!不可在线程创建后立即执行join或者get求值,否则将会导致同步执行,需先转化为CompletableFuture集合或者数组在求值

List<String> futureList = list.stream()
.map(user -> CompletableFuture.supplyAsync(user::getName, executor))
     // 在转化成线程后最好不要直接求值,因为求值会使得线程阻塞,此时下一个线程转化则会需要上一个线程求值完之后才开始转化(被阻塞),因此会变成同步执行而非异步执行,执行所消耗的时长是累加的!!!
.map(CompletableFuture::join)
.collect(Collectors.toList());

 

allOf方法:所有线程执行都执行完

@Test
public void stream() {
    List<test.VcUser> list = Arrays.asList(
            new VcUser("demo1"),
            new VcUser("demo2"),
            new VcUser("demo3")
    );
    // 设定线程数量与集合长度取最小值,设定的线程数量并非越多越好,够用就行
    final Executor executor = Executors.newFixedThreadPool(Math.min(list.size(), 10), runnable -> {
        Thread thread = new Thread(runnable);
        // 新建一个守护线程,防止 一个线程异常导致其他线程无法执行
        thread.setDaemon(true);
        return thread;
    });

    // 将集合转化为用线程来处理数据(将同步转化为异步),提高执行效率,executor为自定义的线程池
    CompletableFuture[] futureList = list.stream()
            .map(user -> CompletableFuture.supplyAsync(user::getName, executor))
        // 将CompletableFuture集合转化为数据 .toArray(CompletableFuture[]::new); CompletableFuture<Void> voids = CompletableFuture.allOf(futureList);
   // 注意:这里会阻塞,需要等待所有线程执行完成 voids.join(); }

 

anyOf:只要有一个线程执行完即可,用法与allOf差不多

 

posted @ 2018-02-02 16:10  antlord  阅读(252)  评论(0编辑  收藏  举报