zoukankan      html  css  js  c++  java
  • 线程池怎么做到主动回调

    某些业务场景需要在一个异步操作完成后做一个回调,如果使用Future有个问题,需要主动调用get然后再执行逻辑。但是异步逻辑不知道什么时候结束,所以推荐回调的方式处理比较优雅,本文总结了三种方式可以实现此类需求。

    1、CompletableFuture

    Future可以明确地完成(设定其值和状态),并且可以被用作CompletionStage ,支持有关的功能和它的完成时触发动作。

    当两个或多个线程试图completecompleteExceptionally ,或cancel一个CompletableFuture,只有一个成功。

    除了直接操作状态和结果的这些和相关方法外,CompletableFuture还实现了接口CompletionStage ,具有以下策略:

    • 异步方法的依赖完成提供的操作可以由完成当前CompletableFuture的线程或完成方法的任何其他调用者执行。
    • 所有不使用显式Executor参数的异步方法都使用ForkJoinPool.commonPool()执行 (除非它不支持至少两个并行级别,在这种情况下,使用新的线程)。 为了简化监视,调试和跟踪,所有生成的异步任务都是标记接口CompletableFuture.AsynchronousCompletionTask的实例
    • 所有CompletionStage方法都是独立于其他公共方法实现的,因此一个方法的行为不会受到子类中其他方法的覆盖的影响。

    CompletableFuture还实施Future ,具有以下政策:

    • 由于(不同于FutureTask ),这个类不能直接控制导致其完成的计算,所以取消被视为另一种形式的异常完成。 方法cancel具有相同的效果completeExceptionally(new CancellationException()) 。 方法isCompletedExceptionally()可用于确定CompletableFuture是否以任何特殊方式完成。
    • 如果使用CompletionException异常完成,方法get()get(long, TimeUnit)将抛出与对应CompletionException中保持的相同原因的ExecutionException。 为了简化大多数情况下的使用,此类还定义了方法join()getNow(T) ,而是在这些情况下直接抛出CompletionException。
    public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
    public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
    public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor);
    

    2、Guava 的 ListenableFuture

    ListenableFuture 是对原有 Future 的增强,可以用于监听 Future 任务的执行状况,是执行成功还是执行失败,并提供响应的接口用于对不同结果的处理。简单来说就是他提供了一个回调接口,在任务结束时可以主动去做通知调用,有点主动推的感觉。

    public class ListenFutureTest {  
    
        public static void main(String[] args) {  
            testListenFuture();  
        }  
    
        public static void testListenFuture() {  
            System.out.println("主任务执行完,开始异步执行副任务1.....");  
            ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5));  
            ListenableFuture<String> future = pool.submit(new Task());  
            Futures.addCallback(future, new FutureCallback<String>() {  
                @Override  
                public void onSuccess(String result) {  
                    System.out.println("成功,结果是:" + result);  
                }  
    
                @Override  
                public void onFailure(Throwable t) {  
                    System.out.println("出错,业务回滚或补偿");  
                }  
            });  
            System.out.println("副本任务启动,回归主任务线,主业务正常返回2.....");  
        }  
    }  
    
    class Task implements Callable<String> {  
    
        @Override  
        public String call() throws Exception {  
            TimeUnit.SECONDS.sleep(1);  
           // int a =1/0;  
            return "task done";  
        }  
    } 
    

    3、RxJava2

    推荐使用RxJava2,具有背压和默认线程调度功能。

        ExecutorService executor = Executors.newFixedThreadPool(2);
        System.out.println("MAIN: " + Thread.currentThread().getId());
        Callable<String> callable = () -> {
            System.out.println("callable [" + Thread.currentThread().getId() + "]: ");
            Path filePath = Paths.get("build.gradle");
            return Files.readAllLines(filePath).stream().flatMap(s -> Arrays.stream(s.split
                    (""))).count() + "";
        };
    
        Future<String> future = executor.submit(callable);
    
        Consumer<String> onNext = v -> System.out
                .println("consumer[" + Thread.currentThread().getId() + "]:" + v);
    
        Flowable.fromCallable(callable).subscribe(onNext);
        Flowable.fromFuture(future).subscribe(onNext);
        System.out.println("END");
    

    参考:

    [RxJava2 响应式编程介绍] https://zouzhberk.github.io/rxjava-study/

    扫描二维码,关注公众号“猿必过”

    file

    回复 “面试题” 自行领取吧。

    微信群交流讨论,请添加微信号:zyhui98,备注:面试题加群

    本文由猿必过 YBG 发布

    禁止未经授权转载,违者依法追究相关法律责任

    如需授权可联系:zhuyunhui@yuanbiguo.com

  • 相关阅读:
    UML第一次编程作业
    css文本属性
    css文字属性
    Qobject设置对象名称和属性
    m3u8
    easyUI tree jQuery
    easyUI layout
    正则表达式
    Spring mvc 数据验证框架注解
    blur和click事件的先后顺序问题
  • 原文地址:https://www.cnblogs.com/javago/p/14466698.html
Copyright © 2011-2022 走看看