新聞?lì)怉pp (MVP + RxJava + Retrofit+Dagger+ARouter)性能優(yōu)化之線程優(yōu)化

Github地址:新聞?lì)怉pp (MVP + RxJava + Retrofit+Dagger+ARouter)

線程調(diào)度原理

  • 任意時(shí)刻,只有一個(gè)線程調(diào)用CPU,處于運(yùn)行時(shí)狀態(tài)
  • 多線程并發(fā):輪流獲取CPU使用權(quán)
  • JVM負(fù)責(zé)線程調(diào)度:按照特定機(jī)制分配CPU使用權(quán)

線程調(diào)度模型

  • 分時(shí)調(diào)度模型:輪流獲取,均分cpu時(shí)間
  • (java虛擬機(jī)采用)搶占式調(diào)度模型:優(yōu)先級(jí)高的獲取

Android線程調(diào)度

nice值

  • process中定義的
  • 值越小,優(yōu)先級(jí)越高
  • 默認(rèn)是THREAD_PRIORITY_DEFAULT =0


    優(yōu)先級(jí).png

cgroup

  • 更嚴(yán)格的群組(前臺(tái)和后臺(tái))調(diào)度策略
  • 保證前臺(tái)線程可以獲取到更多的cpu
    哪些線程會(huì)移動(dòng)到后臺(tái)group:1.手動(dòng)設(shè)置優(yōu)先級(jí)低的 2.不在前臺(tái)運(yùn)行的應(yīng)用程序的線程

1.線程過多會(huì)導(dǎo)致CPU切換頻繁,降低線程運(yùn)行效率
2.正確認(rèn)識(shí)任務(wù)重要性j決定哪種優(yōu)先級(jí)
3.優(yōu)先級(jí)具有繼承性

android異步方式匯總

Thread

  • 最簡(jiǎn)單,最常見的異步方式(最不推薦)
  • 不易復(fù)用,頻繁創(chuàng)建及銷毀開銷大
  • 復(fù)雜場(chǎng)景不易使用

HandlerThread

  • 自帶消息循環(huán)的線程
  • 串行執(zhí)行
  • 長(zhǎng)時(shí)間運(yùn)行,不斷從隊(duì)列中獲取任務(wù)

IntentService

  • 繼承自Service在內(nèi)部創(chuàng)建HandlerThread
  • 異步,不占用主線程
  • 優(yōu)先級(jí)較高,不易輕易被kill

AsyncTask

  • android提供的工具類
  • 無需自己處理線程
  • 需注意版本不一致問題

線程池

  • java提供的線程池
  • 易復(fù)用減少頻繁創(chuàng)建,銷毀的時(shí)間
  • 功能強(qiáng)大:定時(shí),任務(wù)隊(duì)列,并發(fā)數(shù)控制等

Rxjava

  • 由強(qiáng)大的Scheduler集合提供
  • 不同類型的區(qū)分:IO,Computation

Android線程優(yōu)化實(shí)戰(zhàn)

異步使用規(guī)則

  • 嚴(yán)禁直接new Thread
  • 提供基礎(chǔ)線程池供各個(gè)業(yè)務(wù)線使用
    避免各個(gè)業(yè)務(wù)線各自維護(hù)一套線程池,導(dǎo)致線程數(shù)過多
  • 根據(jù)任務(wù)類型選擇合適的異步方式
  • 創(chuàng)建線程必須命名
    方便定位線程歸屬
    運(yùn)行期Thread.currentThread.setName修改名字
  • 關(guān)鍵異步任務(wù)監(jiān)控
    異步不等于不耗時(shí)
    AOP的方式實(shí)現(xiàn)監(jiān)控
  • 重視優(yōu)先級(jí)設(shè)置
    Process.setThredPriority()
    可以設(shè)置多次

實(shí)戰(zhàn)

  • 第一種方式:Executors,會(huì)提示:手動(dòng)創(chuàng)建線程池,效果會(huì)更好哦
public class ThreadPoolUtils {
    /**
     * 會(huì)提示:手動(dòng)創(chuàng)建線程池,效果會(huì)更好哦
     */
    private static ExecutorService sService = Executors.newFixedThreadPool(5, new ThreadFactory() {
        @Override
        public Thread newThread(@NonNull Runnable runnable) {
            Thread thread = new Thread();
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            thread.setName("ThreadPoolUtils's ExecutorService");
            return thread;
        }
    });

    public static ExecutorService getService() {
        return sService;
    }
}

使用

     ThreadPoolUtils.getService().execute(new Runnable() {
            @Override
            public void run() {
                //提高優(yōu)先級(jí)
                Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                String oldName = Thread.currentThread().getName();
                //方便查看哪個(gè)線程報(bào)錯(cuò)
                Thread.currentThread().setName("MainActivity Thread Name");
                Thread.currentThread().setName(oldName);
            }
        });
  • 第二種方式:手動(dòng)創(chuàng)建線程池
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            return new Thread(r, "ThreadPoolUtils's ThreadFactory" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);
    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR;


    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
    public static ThreadPoolExecutor getThreadPoolExecutor() {
        return THREAD_POOL_EXECUTOR;
    }

鎖定線程創(chuàng)建者

鎖定線程創(chuàng)建背景

  • 項(xiàng)目變大之后收斂線程
  • 項(xiàng)目源碼,三方庫,aar中都有線程的創(chuàng)建
  • 避免惡化的一種監(jiān)控預(yù)防手段

方案分析

  • 創(chuàng)建線程的位置獲取堆棧
  • 所有的異步方式都會(huì)走到new Thread
  • 比較適合hook手段
    找hook點(diǎn):構(gòu)造函數(shù)或者特定方法
    Thread的構(gòu)造函數(shù)

優(yōu)雅的方案:ARTHook

  • 掛鉤,將額外的代碼鉤住原有的方法,修改執(zhí)行邏輯
  • 框架:Epic(不能帶到線上環(huán)境)
        DexposedBridge.hookAllConstructors(Thread.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Thread thread = (Thread) param.thisObject;
                LogUtils.i(thread.getName() + " stack " + Log.getStackTraceString(new Throwable()));
            }
        });

線程收斂方案

  • 直接依賴線程庫
  • 缺點(diǎn):線程庫更新可能會(huì)導(dǎo)致基礎(chǔ)庫更新
  • 基礎(chǔ)庫內(nèi)部暴露API:setExecutor
  • 初始化的時(shí)候注入統(tǒng)一的線程庫
  • 代碼。工具類里面添加代碼(UIUtils)
    private static ExecutorService sExecutorService;

    public static void setExecutorService(ExecutorService executorService) {
        sExecutorService = executorService;
    }

    public static void exectur(Runnable runnable) {
        //如果外部庫不為空,則使用外部,否則使用自己的
        if (sExecutorService != null) {
            sExecutorService.execute(runnable);
        } else {
            ThreadPoolUtils.getService().execute(runnable);
        }
    }

注意:1.要區(qū)分任務(wù)類型:IO還是CPU密集型,IO就是上面優(yōu)化實(shí)戰(zhàn)的第一種方式Executors,CPU就是第二種方式手動(dòng)創(chuàng)建
2.IO密集型任務(wù)不消耗CPU,核心池可以很大
3.CPU密集型任務(wù):核心池大小h和CPU核心數(shù)有關(guān)

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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