Universal-Image-Loader源碼解析之線程管理

UIL中包括一下封裝的任務(wù):

  • DisplayImageTask
  • LoadAndDisplayImageTask
  • ProcessAndDisplayImageTask
    它們都在ImageLoadEngine中得到統(tǒng)一調(diào)度執(zhí)行。

線程需要關(guān)注的幾個(gè)方面:

線程池類型

創(chuàng)建線程池的構(gòu)造方法:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
幾種常見(jiàn)線程池.png
  • 對(duì)于需要保證所有提交的任務(wù)都要被執(zhí)行的情況,或者任務(wù)屬于耗時(shí)長(zhǎng)但是數(shù)量少的,使用FixedThreadPool
  • 如果限定只能使用一個(gè)線程進(jìn)行任務(wù)處理,使用SingleThreadExecutor
  • 如果希望提交的任務(wù)盡快分配線程執(zhí)行,或者說(shuō)任務(wù)量大且每個(gè)任務(wù)耗時(shí)比較少的,使用CachedThreadPool
  • 如果業(yè)務(wù)上允許任務(wù)執(zhí)行失敗,或者任務(wù)執(zhí)行過(guò)程可能出現(xiàn)執(zhí)行時(shí)間過(guò)長(zhǎng)進(jìn)而影響其他業(yè)務(wù)的應(yīng)用場(chǎng)景,可以通過(guò)使用限定線程數(shù)量的線程池以及限定長(zhǎng)度的隊(duì)列進(jìn)行容錯(cuò)處理。
UIL中的三個(gè)線程池.png
UIL中線程池的配置.png

UIL線程執(zhí)行

ImageLoader

            ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,
                    options, listener, progressListener, engine.getLockForUri(uri));
            LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,
                    defineHandler(options));
            if (options.isSyncLoading()) {
                displayTask.run();
            } else {
                engine.submit(displayTask);
            }

ImageLoadEngine

    void submit(final LoadAndDisplayImageTask task) {
        taskDistributor.execute(new Runnable() {
            @Override
            public void run() {
                File image = configuration.diskCache.get(task.getLoadingUri());
                boolean isImageCachedOnDisk = image != null && image.exists();
                initExecutorsIfNeed();
                if (isImageCachedOnDisk) {
                    taskExecutorForCachedImages.execute(task);
                } else {
                    taskExecutor.execute(task);
                }
            }
        });
    }
  • taskDistributor:主要任務(wù)就是根據(jù)磁盤(pán)是否有緩存,再來(lái)分配任務(wù)。由于在每創(chuàng)建一個(gè)新的線程的時(shí)候都需要讀取一下磁盤(pán),屬于IO操作。需要圖片緩存的應(yīng)用一般在需要加載圖片的時(shí)候,同時(shí)創(chuàng)建很多(>5)線程,這些線程一般來(lái)得猛去的也快,存活時(shí)間不必太長(zhǎng)。
  • taskExecutorForCachedImages:主要任務(wù)就是將磁盤(pán)上緩存的圖片解碼出來(lái),并作后續(xù)處理,再顯示
  • taskExecutor:主要任務(wù)就是負(fù)責(zé)一個(gè)圖片完整的從網(wǎng)絡(luò)加載到磁盤(pán)緩存、內(nèi)存緩存、預(yù)處理、后續(xù)處理、展示等。

它有如下幾個(gè)主要方法:

    private Executor createTaskExecutor() {
        return DefaultConfigurationFactory
                .createExecutor(configuration.threadPoolSize, configuration.threadPriority,
                configuration.tasksProcessingType);
    }
    void pause() {
        paused.set(true);
    }

    void resume() {
        paused.set(false);
        synchronized (pauseLock) {
            pauseLock.notifyAll();
        }
    }

    void stop() {
        if (!configuration.customExecutor) {
            ((ExecutorService) taskExecutor).shutdownNow();
        }
        if (!configuration.customExecutorForCachedImages) {
            ((ExecutorService) taskExecutorForCachedImages).shutdownNow();
        }

        cacheKeysForImageAwares.clear();
        uriLocks.clear();
    }

其中shutdownNow()方法會(huì)終止線程池中的執(zhí)行

而這個(gè)pause()resume()方法,在多圖列表滑動(dòng)時(shí),可以通過(guò)調(diào)用此方法,暫停線程池中任務(wù)的執(zhí)行以減輕cpu的負(fù)擔(dān),達(dá)到流暢滑動(dòng)的目的。

LoadAndDisplayImageTask中,run()方法執(zhí)行之前,都會(huì)檢查一下 waitIfPaused()方法看此任務(wù)是否暫停,如果是,則先把線程鎖鎖上,然后進(jìn)入等待。

    private boolean waitIfPaused() {
        AtomicBoolean pause = engine.getPause();
        if (pause.get()) {
            synchronized (engine.getPauseLock()) {
                if (pause.get()) {
                    L.d(LOG_WAITING_FOR_RESUME, memoryCacheKey);
                    try {
                        engine.getPauseLock().wait();
                    } catch (InterruptedException e) {
                        L.e(LOG_TASK_INTERRUPTED, memoryCacheKey);
                        return true;
                    }
                    L.d(LOG_RESUME_AFTER_PAUSE, memoryCacheKey);
                }
            }
        }
        return isTaskNotActual();
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容