zoukankan      html  css  js  c++  java
  • Guava future

    减少主函数的等待时间,使得多任务能够异步非阻塞执行

    ListenableFuture是可以监听的Future,它是对java原生Future的扩展增强。Future表示一个异步计算任务,当任务完成时可以得到计算结果。如果希望计算完成时马上就拿到结果展示给用户或者做另外的计算,就必须使用另一个线程不断的查询计算状态。这样做会使得代码复杂,且效率低下。如果使用ListenableFuture,Guava会帮助检测Future是否完成了,如果完成就自动调用回调函数,这样可以减少并发程序的复杂度。

    1、MoreExecutors

         该类是final类型的工具类,提供了很多静态方法。例如listeningDecorator方法初始化ListeningExecutorService方法,使用此实例submit方法即可初始化ListenableFuture对象。

    2、ListeningExecutorService

         该类是对ExecutorService的扩展,重写ExecutorService类中的submit方法,返回ListenableFuture对象。

    3、ListenableFuture

         该接口扩展了Future接口,增加了addListener方法,该方法在给定的excutor上注册一个监听器,当计算完成时会马上调用该监听器。不能够确保监听器执行的顺序,但可以在计算完成时确保马上被调用。

    4、FutureCallback

         该接口提供了OnSuccess和OnFailuren方法。获取异步计算的结果并回调。

    5、Futures

         该类提供和很多实用的静态方法以供使用。

    6、ListenableFutureTask

         该类扩展了FutureTask类并实现ListenableFuture接口,增加了addListener方法。

    7、实例代码

    package listenablefuture;
    
    import com.google.common.util.concurrent.*;
    
    import java.util.concurrent.*;
    
    /**
     * @author xfyou
     * @date 2018/11/2
     */
    public class ListenableFutureTest {
    
        private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("test-pool-%d").build();
        private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(false), THREAD_FACTORY);
        private static final ListeningExecutorService SERVICE = MoreExecutors.listeningDecorator(EXECUTOR_SERVICE);
    
        public static void main(String[] args) {
            // 可以无阻塞的实现多个任务的异步回调
            for (int i = 0; i < 10; i++) {
                ListenableFuture<Boolean> booleanTask = SERVICE.submit(new Callable<Boolean>() {
                    @Override
                    public Boolean call() {
                        try {
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return true;
                    }
                });
    
                try {
                    // 使用get()方法会导致当前主线程一直阻塞直到异步线程的任务执行完成
                    System.out.println(booleanTask.get());
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
    
                Futures.addCallback(booleanTask, new FutureCallback<Boolean>() {
                    @Override
                    public void onSuccess(Boolean result) {
                        System.out.println("BooleanTask: " + result);
                    }
    
                    @Override
                    public void onFailure(Throwable t) {
                    }
                });
    
                ListenableFuture<String> stringTask = SERVICE.submit(new Callable<String>() {
                    @Override
                    public String call() {
                        return "Hello World";
                    }
                });
                Futures.addCallback(stringTask, new FutureCallback<String>() {
                    @Override
                    public void onSuccess(String result) {
                        System.out.println(result);
                    }
    
                    @Override
                    public void onFailure(Throwable t) {
                    }
                });
            }
        }
    
    }

    Java future 和 Guava future的对比

    Future 具有局限性。在实际应用中,当需要下载大量图片或视频时,可以使用多线程去下载,提交任务下载后,可以从多个Future中获取下载结果,由于Future获取任务结果是阻塞的,所以将会依次调用Future.get()方法,这样的效率会很低。很可能第一个下载速度很慢,则会拖累整个下载速度。

    Future主要功能在于获取任务执行结果和对异步任务的控制。但如果要获取批量任务的执行结果,从上面的例子我们已经可以看到,单使用 Future 是很不方便的。其主要原因在于:一方面是没有好的方法去判断第一个完成的任务;另一方面是 Future的get方法 是阻塞的,使用不当会造成线程的浪费。第一个问题可以用 CompletionService 解决,CompletionService 提供了一个 take() 阻塞方法,用以依次获取所有已完成的任务。第二个问题可以用 Google Guava 库所提供的 ListeningExecutorService 和 ListenableFuture 来解决。除了获取批量任务执行结果时不便,Future另外一个不能做的事便是防止任务的重复提交。要做到这件事就需要 Future 最常见的一个实现类 FutureTask 了。Future只实现了异步,而没有实现回调,主线程get时会阻塞,可以轮询以便获取异步调用是否完成。

    在实际的使用中建议使用Guava ListenableFuture来实现异步非阻塞,目的就是多任务异步执行,通过回调的方方式来获取执行结果而不需轮询任务状态。

     

  • 相关阅读:
    开发了套三维光学扫描仪,可以技术转让
    见微知著 带你透过内存看 Slice 和 Array的异同
    Goland 这些技巧,学会开发效率翻倍!
    不懂汇编,也能看懂的 Go interface 原理分析
    win10创建删除文件文件夹需刷新才更新问题
    转载:java中DAO层、Service层、Control层的说明
    代码习惯
    查看网站的服务器和使用的技术
    flutter: CSS规则映射flutter控件-position
    android对话框透传Touch事件
  • 原文地址:https://www.cnblogs.com/frankyou/p/9890215.html
Copyright © 2011-2022 走看看