ArchTaskExecutor 源码分析

ArchTaskExecutor 源码分析

Android小彩虹2021-07-12 15:23:47180A+A-

位于包 :
androidx.arch.core.executor
++++TaskExecutor
++++ArchTaskExecutor
++++DefaultTaskExecutor

复习 Jetpack 时发现了 androidx.arch.core.executor 包中有一个线程池实现类 ArchTaskExecutor,内部实现了切换到主线程的功能。

使用的方式十分顺滑:

//切换到主线程
ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable{

});

//子线程执行
ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable{

});

先看 ArchTaskExecutor 暴露的方法:

  • executeOnDiskIO(Runnable runnable)
  • postToMainThread(Runnable runnable)
  • Executor getMainThreadExecutor()
  • Executor getIOThreadExecutor()
  • boolean isMainThread()
  • void setDelegate(TaskExecutor taskExecutor)

分析具体的方法之前看下 ArchTaskExecutor 类的构造方式:

ArchTaskExecutor 继承自抽象类 TaskExecutor ,TaskExecutor 很简单,只有4个方法,其中可以看到方法executeOnMainThread(Runnable runnable) 中的逻辑是如果任务不是在主线程上,那么将调用 postToMainThread(runnable) 将任务切换至主线程中执行。

public abstract class TaskExecutor {

    public abstract void executeOnDiskIO(@NonNull Runnable runnable);

    public abstract void postToMainThread(@NonNull Runnable runnable);

    public void executeOnMainThread(@NonNull Runnable runnable) {
        if (isMainThread()) {
            runnable.run();
        } else {
            postToMainThread(runnable);
        }
    }

    public abstract boolean isMainThread();
}

接着看 ArchTaskExecutorArchTaskExecutor 实现了一个单例提供访问实例入口:

public class ArchTaskExecutor extends TaskExecutor {
    
    private static volatile ArchTaskExecutor sInstance;

    private TaskExecutor mDelegate;

    private TaskExecutor mDefaultTaskExecutor;
    ...
    
    @NonNull
    public static ArchTaskExecutor getInstance() {
        if (sInstance != null) {
            return sInstance;
        }
        synchronized (ArchTaskExecutor.class) {
            if (sInstance == null) {
                sInstance = new ArchTaskExecutor();
            }
        }
        return sInstance;
    }
    
    private ArchTaskExecutor() {
        mDefaultTaskExecutor = new DefaultTaskExecutor();
        mDelegate = mDefaultTaskExecutor;
    }
}

从源码中还发现有 mDelegatemDefaultTaskExecutor,其中 mDelegateArchTaskExecutor 实现的代理类,承担功能的具体实现。mDefaultTaskExecutor 是已实现的默认线程池代理类,mDelegate 默认被赋予 mDefaultTaskExecutor 的实例,同时支持外部自定义实现线程池。

public class ArchTaskExecutor extends TaskExecutor {
        ...
            
    //设置自定义的线程池        
    public void setDelegate(@Nullable TaskExecutor taskExecutor) {
        mDelegate = taskExecutor == null ? mDefaultTaskExecutor : taskExecutor;
    }
}

再看下一开始讲到的 ArchTaskExecutor 中暴露的方法实现:

public class ArchTaskExecutor extends TaskExecutor {
        ...
            
    //提供主线程的对象获取
    @NonNull
    private static final Executor sMainThreadExecutor = new Executor() {
        @Override
        public void execute(Runnable command) {
            getInstance().postToMainThread(command);
        }
    };

    //提供子线程的对象获取
    @NonNull
    private static final Executor sIOThreadExecutor = new Executor() {
        @Override
        public void execute(Runnable command) {
            getInstance().executeOnDiskIO(command);
        }
    };
    
	public void setDelegate(@Nullable TaskExecutor taskExecutor) {
        mDelegate = taskExecutor == null ? mDefaultTaskExecutor : taskExecutor;
    }

    @Override
    public void executeOnDiskIO(Runnable runnable) {
        mDelegate.executeOnDiskIO(runnable);
    }

    @Override
    public void postToMainThread(Runnable runnable) {
        mDelegate.postToMainThread(runnable);
    }

    @NonNull
    public static Executor getMainThreadExecutor() {
        return sMainThreadExecutor;
    }

    @NonNull
    public static Executor getIOThreadExecutor() {
        return sIOThreadExecutor;
    }

    @Override
    public boolean isMainThread() {
        return mDelegate.isMainThread();
    }
}

以上的几个方法都是直接由代理类直接实现。
那么,接下来再看看代理类 DefaultTaskExecutor 的实现。

同样的,DefaultTaskExecutor 也是继承抽象类 TaskExecutor,然后实现了父类的抽象方法,DefaultTaskExecutor 完整源码如下

public class DefaultTaskExecutor extends TaskExecutor {

    private final Object mLock = new Object();

    private final ExecutorService mDiskIO = Executors.newFixedThreadPool(2, new ThreadFactory() {
        private static final String THREAD_NAME_STEM = "arch_disk_io_%d";

        private final AtomicInteger mThreadId = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName(String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement()));
            return t;
        }
    });

    @Nullable
    private volatile Handler mMainHandler;

    @Override
    public void executeOnDiskIO(Runnable runnable) {
        mDiskIO.execute(runnable);
    }

    @Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = new Handler(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }

    @Override
    public boolean isMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }
}

经过上边分析:

  1. DefaultTaskExecutor 继承 TaskExecutor,并实现了父类方法
  2. 内部实现了线程池 Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory),所以 ArchTaskExecutor 实际上是对 Executors 的一层包装。
  3. 实现了 Handler ,将任务切换至主线程。

总结:

ArchTaskExecutor 使用代理模式实现了一个内部的线程池 DefaultTaskExecutor 提供使用,同时支持切换主线程的功能。其中如果使用者没有设置自己的 TaskExecutor ,那么 ArchTaskExecutor 将会使用 DefaultTaskExecutor 作为默认实现的线程池。

后面如果需要用到线程池的地方,就不用再自己写一堆实现方法了,直接调用 ArchTaskExecutor 就行了,如果不满足要求,就自己再定义一个 TaskExecutor

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1

联系我们