1.《Exploring in UE4》多线程机制详解[原理分析]
2.JobIntentService源码解析
《Exploring in UE4》多线程机制详解[原理分析]
多线程是优化项目性能的重要方式之一,游戏也不例外。码详尽管有观点认为“游戏不适合利用多线程优化”,源码o源但实际上游戏中多线程的码详应用非常广泛,如渲染模块、源码o源物理模块、码详安心源码网络通信、源码o源音频系统、码详IO等。源码o源UE4引擎运行时展示的码详线程数量可能比您想象的要多。
尽管UE4遵循C++标准,源码o源但它并没有使用std::thread,码详红中麻将程序源码而是源码o源自实现了一套多线程机制,这类似于Java的码详用法。如果您想使用std::thread,源码o源也是完全可以的。
在UE4中,您可以创建继承自FRunnable接口的单个线程,也可以直接创建AsyncTask来调用线程池中空闲的线程,还可以通过TaskGraph系统异步完成自定义任务。尽管本质相同,但用法不同,理解上也需要花费不少时间。怎么查源码路径本文将对各种机制进行分析并总结,但不会深入讨论线程的实现原理和线程安全等内容。由于个人接触多线程编程时间不长,有些内容可能不够准确,欢迎共同讨论。
首先,我们从最基本的方式来创建线程,即创建一个继承自FRunnable的类,将任务分发给其他线程执行。FRunnable是一个简单的类,包含5到6个函数接口,补码与源码相加为了与真正的线程区分,我们将其称为“线程执行体”。
关于FQueuedThreadPool线程池,它类似于一般的线程池实现,维护了多个线程FQueuedThread和多个任务队列IQueuedWork。在线程池中,所有线程都是FQueuedThread类型,它们是继承自FRunnable的线程执行体,每个FQueuedThread包含一个FRunnableThread作为内部成员。
接下来,我们谈谈更复杂的dubbo协议源码分析AsyncTask系统,它是一套基于线程池的异步任务处理系统。在使用搜索引擎搜索UE4多线程时,可能会看到类似官方代码中的异步处理解决方案示例。这个所谓的多线程用法看似简单,但实际上也是基于Runnable的方式实现的,只是封装得更深,需要深入源码才能理解其原理。
TaskGraph系统是UE4一套抽象的异步任务处理系统,可以创建多个多线程任务,并指定任务之间的依赖关系,按照该关系依次处理任务。具体实现方式网上有很多案例,建议先了解其用法。
TaskGraph系统中的任务与线程可以创建多个Task任务并分配给不同的线程执行。在TaskGraph系统中,任务类也是我们自行创建的,如FTickFunctionTask、FReturnGraphTask等,其中需要声明DoTask函数来表示要执行的任务内容,GetDesiredThread函数来表示要在哪个线程上执行。
最后,我们总结了三种使用多线程的方式,每种机制都有很多技术点值得我们深入学习。对于消耗大、复杂的任务,不建议使用TaskGraph。对于简单的任务或想方便实现线程之间的依赖等待关系,可以直接使用TaskGraph。
JobIntentService源码解析
Android 8.0引入了更严格的系统资源管控,包括后台限制规则。
在Android 8.0中,禁止应用在后台运行时创建Service。
若应用在后台运行,将会收到错误提示。
JobIntentService是Android 8.0中新增的类,继承自Service。
该类用于执行加入队列的任务。对于Android 8.0及以上系统,JobIntentService任务将通过JobScheduler.enqueue执行,而8.0以下系统则继续使用Context.startService。
JobIntentService使用便捷,只需调用YourService.enqueueWork(context, new Intent())方法。
相较于JobService,JobIntentService简化了操作,开发者无需关注其生命周期,避免了在后台运行时创建Service导致的crash问题,且通过静态方法即可启动。
源码解析如下:首先记录几个关键变量的含义。
在Android 8.0以上的系统中,执行流程如下。
work的具体逻辑处理在何处?
通过JobService的工作原理,查找onStartJob方法。
最终,处理work的逻辑会流转至AsyncTask中,通过protected abstract void onHandleWork(@NonNull Intent intent)方法实现。
子类需实现jobIntentService处理work,使用线程池的AsyncTask执行,无需考虑主线程阻塞问题。
针对Android 8.0以下系统,流程如下:回到onStartCommand方法。
同样,最终会流转至Asynctask任务执行onHandleWork。