更多信息请访问:https://harmonyos.51cto.com,与华为官方概述共建的鸿蒙技术社区不同的应用程序运行在各自独立的进程中。当以任何形式启动应用程序时,系统都会为其创建一个进程,该进程将继续运行。当进程完成当前任务处于等待状态,系统资源不足时,系统自动回收。当应用程序启动时,系统会为该应用程序创建一个称为“主线程”的执行线程。该线程随应用程序一起创建或消失,是应用程序的核心线程。UI界面的显示、更新等操作都在主线程上进行。主线程也称为UI线程。默认情况下,所有操作都在主线程上执行。如果需要执行耗时的任务(如下载文件、查询数据库),可以创建其他线程进行处理。如果应用的业务逻辑比较复杂,可能需要创建多个线程来执行多个任务。在这种情况下,代码复杂且难以维护,任务和线程之间的交互也会更加复杂。为了解决这个问题,开发者可以使用TaskDispatcher来分发不同的任务。TaskDispatcher简介TaskDispatcher是一个任务调度器,是Ability分发任务的基本接口,隐藏了任务所在线程的实现细节。为了确保应用程序更好的响应能力,我们需要对设计任务进行优先级排序。在UI线程上运行的任务默认以高优先级运行。如果一个任务不需要等待结果,它可以使用低优先级。线程优先级介绍:HIGH:最高任务优先级,比默认优先级和低优先级任务有更高的概率被执行。DEFAULT:默认的任务优先级,比低优先级的任务有更高的概率被执行。LOW:低任务优先级,比高优先级和默认优先级任务执行的几率低。TaskDispatcher有多个实现,每个实现对应不同的任务调度器。分配任务时可以指定任务的优先级,同一个任务分配器分配的任务具有相同的优先级。系统提供的任务调度器包括GlobalTask??Dispatcher、ParallelTask??Dispatcher、SerialTask??Dispatcher、SpecTaskDispatcher。实践一、同步调度任务syncDispatch在当前线程中调度任务并等待任务执行完成。返回前,当前线程会被阻塞/***同步调度任务*/privatevoidsyncDispatch(){TaskDispatcherglobalTask??Dispatcher=getGlobalTask??Dispatcher(TaskPriority.DEFAULT);globalTask??Dispatcher.syncDispatcher(newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"synctask1run");}});HiLog.info(LABEL_LOG,"aftersynctask1");globalTask??Dispatcher.syncDispatch(newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"synctask2run");}});HiLog.info(LABEL_LOG,"aftersynctask2");globalTask??Dispatcher.syncDispatch(newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"synctask3run");}});HiLog.info(LABEL_LOG,"aftersynctask3");}运行然后查看日志:从运行结果可以看出,只有等待任务完成,当前线程才会继续执行,否则当前线程会被阻塞,所以在使用syncDispatch的时候需要注意。如果syncDispatch使用不当,会造成死锁。以下几种情况可能会导致死锁:在专用线程上,使用专用任务调度器执行syncDispatch。在一个串行任务调度器(dispatcher_a)调度的任务中,使用同一个串行任务调度器(dispatcher_a)对象再次调度任务。在串行任务调度器(dispatcher_a)调度的任务中,经过多次调度后,最终使用(dispatcher_a)串行任务调度器进行任务调度。例如:dispatcher_a派发的任务使用dispatcher_b来派发任务,dispatcher_b派发的任务中使用dispatcher_a来派发任务。串行任务调度器(dispatcher_a)调度的任务使用串行任务调度器(dispatcher_b)同步调度任务,dispatcher_b调度的任务使用串行任务调度器(dispatcher_a)同步调度任务。在一定的线程执行顺序下,会导致死锁。2.异步派发任务asyncDispatch派发任务并立即返回。返回值是一个可用于取消任务的接口。/***异步调度任务*/privatevoidasyncDispatch(){TaskDispatcherglobalTask??Dispatcher=getGlobalTask??Dispatcher(TaskPriority.DEFAULT);Revocablerevocable=globalTask??Dispatcher.asyncDispatch(newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG};task}1run,"async));HiLog.info(LABEL_LOG,"afterasynctask1");}运行后查看日志:从运行结果可以看出只有当前线程等待任务完成后才会继续执行,否则当前线程会被阻塞。因此,当使用3.异步延迟调度任务delayDispatch是异步执行的,函数立即返回,延迟指定时间后,会在内部将任务调度到相应的队列中。延迟时间参数只是表示任务dispatcher会在这段时间后将任务添加到队列中,任务实际执行的时间可能会晚于这个时间,比这个值晚多少取决于b队列和内部线程池的可用性。/***异步延迟调度任务*/privatevoiddelayDispatch(){finallongcallTime=System.currentTimeMillis();finallongdelayTime=50L;TaskDispatcherglobalTask??Dispatcher=getGlobalTask??Dispatcher(TaskPriority.DEFAULT);Revocablerevocable=globalTask??Dispatcher.delayDispatcher(newRunnable(){@Oidverrunep(){voHiLog.info(LABEL_LOG,"delayDispatchtask1run");finallongactualDelay=System.currentTimeMillis()-callTime;HiLog.info(LABEL_LOG,"actualDelayTime>=delayTime:%{public}b",(actualDelay>=delayTime));}},delayTime);HiLog.info(LABEL_LOG,"afterdelayDispatchtask1");}运行后查看日志:从运行结果可以看出程序先执行“afterdelayDispatchtask1”,然后执行“delayDispatchtask1run”",最后执行"actualDelayTime>=delayTime:%{public}b",(actualDelay>=delayTime),这里actualDelayTime>=delayTime:true可以看出,延迟时间参数只是表示任务分发器会添加任务这段时间后到队列中,T任务的实际执行时间可能会晚于这个时间。4.任务组Group代表一组任务,这个组中的任务之间存在一定的联系。它由TaskDispatcher执行createDispatchGroup创建并返回。添加任务到任务组,返回取消任务接口。/***TaskGroup*/privatevoiddispatchGroup(){StringdispatcherName="parallelTask??Dispatcher";TaskDispatcherdispatcher=createParallelTask??Dispatcher(dispatcherName,TaskPriority.DEFAULT);//创建任务组。Groupgroup=dispatcher.createDispatchGroup();//将任务1加入任务组,并返回取消任务的接口。dispatcher.asyncGroupDispatch(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"downloadtask1isrunning");}});//将任务1关联的任务2添加到任务组。dispatcher.asyncGroupDispatch(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"downloadtask2isrunning");}});//任务组中的所有任务执行完毕后执行指定任务。dispatcher.groupDispatchNotify(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"theclosetaskisrunningafteralltasksinthegrouparecompleted");}});}运行后查看日志:5.同步设置屏障任务syncDispatchBarrier设置任务执行在任务组Barrier上,同步等待任务组中的所有任务完成后再执行指定的任务。/***同步设置屏障任务*/privatevoidsyncDispatchBarrier(){StringdispatcherName="parallelTask??Dispatcher";TaskDispatcherdispatcher=createParallelTask??Dispatcher(dispatcherName,TaskPriority.DEFAULT);//创建任务组。Groupgroup=dispatcher.createDispatchGroup();//将任务加入任务组,并返回取消任务的接口。dispatcher.asyncGroupDispatch(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"task1isrunning");//1}});dispatcher.asyncGroupDispatch(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"task2isrunning");//2}});dispatcher.syncDispatchBarrier(newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"barrier");//3}});HiLog.info(LABEL_LOG,"aftersyncDispatchBarrier");//4}运行后查看日志:6.异步设置barrier任务asyncDispatchBarrier设置任务执行后直接返回任务组上的barrier,任务组中的所有任务执行完成后执行指定的任务。/***异步设置屏障任务*/privatevoidasyncDispatchBarrier(){TaskDispatcherdispatcher=createParallelTask??Dispatcher("dispatcherName",TaskPriority.DEFAULT);//创建任务组。Groupgroup=dispatcher.createDispatchGroup();//将任务加入任务组,并返回取消任务的接口。dispatcher.asyncGroupDispatch(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"task1isrunning");//1}});dispatcher.asyncGroupDispatch(group,newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"task2isrunning");//2}});dispatcher.asyncDispatchBarrier(newRunnable(){@Overridepublicvoidrun(){HiLog.info(LABEL_LOG,"barrier");//3}});HiLog.info(LABEL_LOG,"afterasyncDispatchBarrier");//4}运行后查看日志:summarythread就像一把双刃剑。用得好,可以给我们带来事半功倍的效果。带来了麻烦,而且这个麻烦不是短时间能解决的(因为发现问题的时候往往是优化期,各个业务相互牵扯),所以这些问题需要严格考虑在项目的早期阶段。更多信息请访问:Harmonyos.51cto.com,与华为官方合作打造的鸿蒙技术社区
