美文网首页
记一次 CompletableFuture 实际使用场景

记一次 CompletableFuture 实际使用场景

作者: smart_dev | 来源:发表于2023-09-08 06:19 被阅读0次

    如果忘记使用方法可参考这篇文章

    项目背景

    • 在开发短视频下载过程中,发现视频下载时机比较靠后,梳理发现其中有一个原因是我们的普通图片是线性下载的逻辑,即单线程顺序下载。
    • 当所有普通图片下载完毕后才会开始展示到页面。
    • 为此,想优化图片下载的总共时间,一个可以减少用户在页面等待时间,即不能及时浏览下一张图片;另一个也能为视频缓存在提前一定的时机,争取到更多的时间。

    那实际问题就转化成了: 如何去开辟多线程(几个为好这里不讨论)同时需要等待结果都回来

    优化方案

    采用多线程下载静态图片,并且等全部任务执行完毕后,再继续往下执行。

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.ExecutorService;
    import java.util.function.Supplier;
    
    public class ImageDownloadManager {
        private static final String TAG = ImageDownloadManager.class.getSimpleName();
        ExecutorService mExecutor;
    
    
        public ImageDownloadManager() {
            mExecutor = ExecutorManager.xxxx();
        }
    
        public List<PictureItem> download(Context context, List<PictureItem> imageList) {
            List<PictureItem> copyList = new CopyOnWriteArrayList<>(imageList);
            List<CompletableFuture> futureList = new ArrayList<>();
            Log.d(TAG, "Start download for all images.");
    
            for (PictureItem item : imageList) {
              
                    CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(new Supplier<Boolean>() {
                        @Override
                        public Boolean get() {
                            boolean isValid = XXXUtils.preLoadImage(xxxx);
                            if (!isValid) {
                                copyList.remove(item);
                            }
                            Log.d(TAG, "A download end, isValid:" + isValid + " url: " + xxx);
                            return isValid;
                        }
                    }, mExecutor);
                    futureList.add(future);
                }
            
    
            CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
            voidCompletableFuture.join();
            Log.d(TAG, "End download for all images. download total count = " + futureList.size()
                    + " ,download fail count = " + (imageList.size() - copyList.size()));
            return new ArrayList<>(copyList);
        }
    }
    

    优化结果

    整体优化后速度提升了 100% - 140%

    项目方案复用需考虑的因素

    1. 线程个数与任务个数的选择协调
    2. 任务类型,前台还是后台,是否紧急

    相关文章

      网友评论

          本文标题:记一次 CompletableFuture 实际使用场景

          本文链接:https://www.haomeiwen.com/subject/yuolvdtx.html