CompletionStage接口方法说明

一、根据阶段正常完成结果的产出型(或者叫函数型):

这一类方法都由上一阶段(或者两个阶段,或者两个阶段中的任意一个)的正常完成结果触发,然后以该结果执行给定的函数,产出新的结果。这里把异步执行的两者形式也列举出来了。

//依赖单个阶段
public  CompletionStage thenApply(Function fn);     // 默认执行方式
public  CompletionStage thenApplyAsync(Function fn);// 默认的异步执行方式
public  CompletionStage thenApplyAsync(Function fn,Executor executor); //自定义的执行方式

//依赖两个阶段都完成
public  CompletionStage thenCombine(CompletionStage other, BiFunction fn);
public  CompletionStage thenCombineAsync(CompletionStage other, BiFunction fn);
public  CompletionStage thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor);

//依赖两个阶段中的任何一个完成
public  CompletionStage applyToEither(CompletionStage other,Function fn);
public  CompletionStage applyToEitherAsync(CompletionStage other,Function fn);
public  CompletionStage applyToEitherAsync(CompletionStage other,Function fn,Executor executor);

代码如下:

Person类

package com.redisson;

/**
 * @Description TODO
 * @Date 2020/7/28 13:41
 * @Author zsj
 */
public class Person {
    public int age;
    public String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

测试类如下:

package com.redisson;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

/**
 * @Description TODO
 * @Date 2020/7/28 9:09
 * @Author zsj
 */
public class MainFour {
    public static void main(String[] args) throws Exception {

//        thenCombineAsync();

//        thenApplyAsync();

        applyToEitherAsync();

        Thread.sleep(10000);
    }


    public static void thenCombineAsync() {

        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person p = new Person();
                p.setAge(10);
                p.setName("p1");
                return p;
            }
        });
        CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person p = new Person();
                p.setAge(20);
                p.setName("p2");
                return p;
            }
        });

        CompletableFuture three = one.thenCombineAsync(two, (p1, p2) -> {
            Person p3 = new Person();
            p3.setAge(p1.getAge());
            p3.setName(p2.getName());
            return p3;

        });
        three.thenAcceptAsync((person) -> {
            System.out.println(person.getAge());
            System.out.println(person.getName());

        }).exceptionally((ee) -> {
            ee.printStackTrace();
            return null;
        });
    }


    public static void thenApplyAsync() {
        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person p = new Person();
                p.setAge(10);
                p.setName("p1");
                return p;
            }
        });

        CompletableFuture two = one.thenApplyAsync((p1) -> {
            Person p2 = new Person();
            p2.setAge(p1.getAge() + 11);
            p2.setName("p2");
            return p2;

        });
        two.thenAcceptAsync((person) -> {
            System.out.println(person.getAge());
            System.out.println(person.getName());

        }).exceptionally((ee) -> {
            ee.printStackTrace();
            return null;
        });
    }


    public static void applyToEitherAsync() {

        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person p = new Person();
                p.setAge(10);
                p.setName("p1");
                return p;
            }
        });
        CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person p = new Person();
                p.setAge(20);
                p.setName("p2");
                return p;
            }
        });

        CompletableFuture three = one.applyToEitherAsync(two, (person) -> {
            Person p3 = new Person();
            p3.setAge(person.getAge());
            p3.setName(person.getName());
            return p3;

        });
        three.thenAcceptAsync((person) -> {
            System.out.println(person.getAge());
            System.out.println(person.getName());

        }).exceptionally((ee) -> {
            ee.printStackTrace();
            return null;
        });
    }


}

 

二、根据阶段正常完成结果的消费型:

这一类方法都由上一阶段(或者两个阶段,或者两个阶段中的任意一个)正常完成的结果触发,然后以该结果执行给定的操作action,但不会对阶段的结果进行影响。这里把异步执行的两者形式也列举出来了。

//依赖单个阶段
public CompletionStage thenAccept(Consumer action);
public CompletionStage thenAcceptAsync(Consumer action);
public CompletionStage thenAcceptAsync(Consumer action, Executor executor);

//依赖两个阶段都完成
public  CompletionStage thenAcceptBoth(CompletionStage other, BiConsumer action);
public  CompletionStage thenAcceptBothAsync(CompletionStage other, BiConsumer action);
public  CompletionStage thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor);

//依赖两个阶段中的任何一个完成
public CompletionStage acceptEither(CompletionStage other, Consumer action);
public CompletionStage acceptEitherAsync(CompletionStage other, Consumer action);
public CompletionStage acceptEitherAsync(CompletionStage other, Consumer action, Executor executor);

测试类如下:

package com.redisson;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

/**
 * @Description TODO
 * @Date 2020/7/17 15:18
 * @Author zsj
 */
public class MainFive {
    public static void main(String[] args) throws Exception {
//        thenAccept();

//        thenAcceptBoth();

        acceptEither();

        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(10000);
    }


    public static void thenAccept() {
        CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p1");
                person.setAge(10);
                return person;
            }
        }).thenAcceptAsync((person) -> {
            System.out.println("age====" + person.getAge());
        });
    }


    public static void thenAcceptBoth() {
        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p1");
                person.setAge(10);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });

        CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p2");
                person.setAge(20);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });
        CompletableFuture three = one.thenAcceptBothAsync(two, (s1, s2) -> System.out.println(s1.getAge() + " " + s2.getName()));

    }


    public static void acceptEither() {

        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p1");
                person.setAge(10);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });

        CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p2");
                person.setAge(20);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });
        one.acceptEitherAsync(two, person -> {
            System.out.println(person.getAge());
        });

    }
}

三、只要求依赖的阶段正常完成的不消耗也不产出型:

这一类方法只要求上一阶段(或者两个阶段,或者两个阶段中的任意一个)正常完成,并不关心其具体结果,从而执行指定的操作cation,但不会对阶段的结果进行影响。这里把异步执行的两者形式也列举出来了。

//依赖单个阶段
public CompletionStage thenRun(Runnable action);
public CompletionStage thenRunAsync(Runnable action);
public CompletionStage thenRunAsync(Runnable action, Executor executor);


//依赖两个阶段都完成
public CompletionStage runAfterBoth(CompletionStage other, Runnable action);
public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action);
public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action, Executor executor);


//依赖两个阶段中的任何一个完成
public CompletionStage runAfterEither(CompletionStage other, Runnable action);
public CompletionStage runAfterEitherAsync(CompletionStage other, Runnable action);
public CompletionStage runAfterEitherAsync(CompletionStage other, Runnable action, Executor executor);

代码如下:

package com.redisson;

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

/**
 * @Description TODO
 * @Date 2020/7/28 15:14
 * @Author zsj
 */
public class MainSix {
    public static void main(String[] args) throws Exception {
//        thenRun();

//        runAfterBoth();

        runAfterEither();

        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(10000);
    }

    public static void thenRun() {
        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Person p = new Person();
                p.setAge(10);
                p.setName("p1");
                return p;
            }
        });

        one.thenRun(() -> System.out.println("hello world"));

    }


    public static void runAfterBoth() {
        //不关心这两个CompletionStage的结果,只关心这两个CompletionStage正常执行完毕,之后在进行操作(Runnable)。
        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p1");
                person.setAge(10);
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });

        CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p2");
                person.setAge(20);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });
        one.runAfterBoth(two, () -> System.out.println("hello world"));

    }


    public static void runAfterEither() {
        //不关心这两个CompletionStage的结果,只关心这两个CompletionStage正常执行完毕,之后在进行操作(Runnable)。
        CompletableFuture one = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p1");
                person.setAge(10);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });

        CompletableFuture two = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Person get() {
                Person person = new Person();
                person.setName("p2");
                person.setAge(20);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return person;
            }
        });

        one.runAfterEither(two, () -> System.out.println("hello world"));
    }
}

 

四、根据正常完成的阶段本身而不是其结果的产出型:

public  CompletionStage thenCompose(Function> fn);
public  CompletionStage thenComposeAsync(Function> fn);
public  CompletionStage thenComposeAsync(Function> fn, Executor executor);

五、不论阶段正常还是异常完成的消耗型:

 public CompletionStage whenComplete(BiConsumer action);
 public CompletionStage whenCompleteAsync(BiConsumer action);
 public CompletionStage whenCompleteAsync(BiConsumer action, Executor executor);

上面的一、二、三、四种类型的方法都需要依赖的阶段正常完成,如果异常完成将导致上面介绍的四种类型的方法最终也异常完成,不会得出我们希望的结果。而whenComplete则不论依赖的上一个阶段是正常完成还是异常完成都不会影响它的执行,但它是一个消耗型接口,即不会对阶段的原来结果产生影响,结合thenCombine综合whenComplete的示例如下:

 

 

@Test
public void thenCombine(){
    String result = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (1 == 1) {
            throw new RuntimeException("测试一下异常情况");
        }

        return "hello ";
    }).thenCombine(CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("return world...");  //会执行
        return "world";
    }), (s1, s2) -> {
        String s = s1 + " " + s2;   //并不会执行
        System.out.println("combine result :"+s); //并不会执行
        return s;
    }).whenComplete((s, t) -> {
        System.out.println("current result is :" +s);
        if(t != null){
            System.out.println("阶段执行过程中存在异常:");
            t.printStackTrace();
        }
    }).join();

    System.out.println("final result:"+result); //并不会执行
}

六、不论阶段正常还是异常完成的产出型:

whenComplete是对不论依赖阶段正常完成还是异常完成时的消耗或者消费,即不会改变阶段的现状,而handle前缀的方法则是对应的产出型方法,即可以对正常完成的结果进行转换,也可以对异常完成的进行补偿一个结果,即可以改变阶段的现状。

 public  CompletionStage handle (BiFunction fn);
 public  CompletionStage handleAsync(BiFunction fn);
 public  CompletionStage handleAsync(BiFunction fn, Executor executor);

 

@Test
public void handle() {
    String result = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //出现异常
        if (1 == 3) {
            throw new RuntimeException("测试一下异常情况");
        }
        return "Tom";
    }).handle((s, t) -> {
        if (t != null) { //出现异常了
            return "John";
        }
        return s; //这里也可以对正常结果进行转换
    }).join();
    System.out.println(result);
}

 

 

 

handle的第一个参数s是上一个阶段的结果,t参数是Throwable类型的异常,这里上一个阶段如果没有抛出异常,那么最终打印的结果是"Tom",现在通过handle对出现异常的情况进行了补偿返回John,所以上例最终其实打印的是"John"。

七、异常完成的产出型:

第五、六两种类型的方法是对于不论依赖的阶段是正常完成还是异常完成的处理,CompletionStage还提供了一个仅当上一个阶段异常完成时的处理,并且可以修改阶段的结果:

 public CompletionStage exceptionally(Function fn);
@Test
public void exceptionally() {
    String result = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (1 == 1) {
            throw new RuntimeException("测试一下异常情况");
        }
        return "s1";
    }).exceptionally(e -> {
        e.printStackTrace(); //e肯定不会null
        return "hello world"; //补偿返回
    }).join();
    System.out.println(result); //打印hello world
}

可见exceptionally只有一个参数e,表示上一个节点的异常,只有上一个阶段异常完成才会被执行,以上示例在异常时返回了新的值"hello world"对出现异常的阶段进行了补偿,所以最终整个阶段不会出现异常,并打印出"hello world"。

八、实现该接口不同实现之间互操作的类型转换方法:

public CompletableFuture toCompletableFuture();

返回一个与此阶段保持相同完成属性的CompletableFuture实例。如果此阶段已经是一个CompletableFuture,那么直接返回该阶段本身,否则此方法的调用可能等效于thenApply(x -> x),但返回一个类型为CompletableFuture的实例。不选择实现该互操作性的CompletionStage实现,可能会抛出UnsupportedOperationException异常

你可能感兴趣的:(Java多线程)