详细解说TaskDispatcher与线程的关系

1.任务优先级的概念

为保证应用有更好的响应性,我们需要设计任务的优先级。在UI线程上运行的任务默认以高优先级运行,如果某个任务无需等待结果,则可以用低优先级。
任务优先级表.png

在分发任务时可以指定任务的优先级,由同一个任务分发器分发出的任务具有相同的优先级。

2.TaskDispatcher

TaskDispatcher是一个任务分发器,它是Ability分发任务的基本接口,隐藏任务所在线程的实现细节。TaskDispatcher具有多种实现,每种实现对应不同的任务分发器

  • GlobalTaskDispatcher
    全局并发任务分发器,由Ability执行getGlobalTaskDispatcher()获取。适用于任务之间没有联系的情况。一个应用只有一个GlobalTaskDispatcher,它在程序结束时才被销毁。
for (int i = 0; i < 1000; i++) {
            //创建GlobalTaskDispatcher
            TaskDispatcher globalTaskDispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
            //执行异步任务
            globalTaskDispatcher.asyncDispatch(new Runnable() {
                @Override
                public void run() {
                    HiLog.error(LABEL_LOG, "getGlobalTaskDispatcher ThreadName:" + Thread.currentThread().getName()
                            + "--ThreadId:" + Thread.currentThread().getId());
                    HiLog.error(LABEL_LOG, "globalTaskDispatcher ID:" + globalTaskDispatcher.hashCode());
                }
            });
 }

输出结果:


结论:
1.GlobalTaskDispatcher中的任务执行是在子线程中执行的,而且是从线程池中创建线程来执行,所以通过GlobalTaskDispatcher来执行的任务是可以进行耗时操作的,但是不能刷新UI。
2.GlobalTaskDispatcher的对象在全局是唯一的,通过不断创建GlobalTaskDispatcher,获取到的hashCode都是唯一的。
3.GlobalTaskDispatcher的线程池核心线程数是一个固定值,我自己测试为32,这个可能跟主机CPU有关系,也可能跟代码实现逻辑有关系,需要进一步等开源代码后验证。

  • ParallelTaskDispatcher
    并发任务分发器,由Ability执行createParallelTaskDispatcher()创建并返回。与GlobalTaskDispatcher不同的是,ParallelTaskDispatcher不具有全局唯一性,可以创建多个。开发者在创建或销毁dispatcher时,需要持有对应的对象引用
String dispatcherName = "parallelTaskDispatcher";
        TaskDispatcher parallelTaskDispatcher = createParallelTaskDispatcher(dispatcherName, TaskPriority.DEFAULT);
        parallelTaskDispatcher.asyncDispatch(new Runnable() {
            @Override
            public void run() {
                HiLog.error(LABEL_LOG, "parallelTaskDispatcher threadName:" + Thread.currentThread().getName()
                        + "--ThreadId:" + Thread.currentThread().getId());
            }
        });
//输出结果:
//parallelTaskDispatcher threadName:PoolThread-1--ThreadId:34627

同样该任务分发器的任务执行在子线程中。

  • SerialTaskDispatcher
    串行任务分发器,由Ability执行createSerialTaskDispatcher()创建并返回。由该分发器分发的所有的任务都是按顺序执行,但是执行这些任务的线程并不是固定的。如果要执行并行任务,应使用ParallelTaskDispatcher或者GlobalTaskDispatcher,而不是创建多个SerialTaskDispatcher。如果任务之间没有依赖,应使用GlobalTaskDispatcher来实现。它的创建和销毁由开发者自己管理,开发者在使用期间需要持有该对象引用。
String dispatcherName = "serialTaskDispatcher";
        TaskDispatcher serialTaskDispatcher = createSerialTaskDispatcher(dispatcherName, TaskPriority.DEFAULT);
        for (int i = 0; i < 1000; i++) {
            //执行异步任务
            int finalI = i;
            serialTaskDispatcher.asyncDispatch(new Runnable() {
                @Override
                public void run() {
                    HiLog.error(LABEL_LOG, "serialTaskDispatcher 执行第" + finalI + " ThreadName:" + Thread.currentThread().getName()
                            + "--ThreadId:" + Thread.currentThread().getId());
                    HiLog.error(LABEL_LOG, "serialTaskDispatcher ID:" + serialTaskDispatcher.hashCode());
                }
            });
        }

也就是说该任务分发器执行的任务会按顺序执行,但是执行的线程不是唯一的,会从线程池里边去取,执行不同的任务可能取到的线程不一致。
  • SpecTaskDispatcher
    专有任务分发器,绑定到专有线程上的任务分发器。目前已有的专有线程为UI线程,通过UITaskDispatcher进行任务分发。
    UITaskDispatcher:绑定到应用主线程的专有任务分发器, 由Ability执行getUITaskDispatcher()创建并返回。 由该分发器分发的所有的任务都是在主线程上按顺序执行,它在应用程序结束时被销毁。
getUITaskDispatcher().asyncDispatch(new Runnable() {
            @Override
            public void run() {
                HiLog.error(LABEL_LOG, "getUITaskDispatcher threadName:" + Thread.currentThread().getName()
                        + "--ThreadId:" + Thread.currentThread().getId());
            }
        });
        getMainTaskDispatcher().asyncDispatch(new Runnable() {
            @Override
            public void run() {
                HiLog.error(LABEL_LOG, "getMainTaskDispatcher threadName:" + Thread.currentThread().getName()
                        + "--ThreadId:" + Thread.currentThread().getId());
            }
        });

输出结果:

getMainTaskDispatcher()和getUITaskDispatcher()的任务都是执行在主线程中,所以在这两个分发器中执行的任务不能进行耗时操作,但是可以进行更新UI操作。

你可能感兴趣的:(详细解说TaskDispatcher与线程的关系)