超值的扬中网站建设,给个网址兄弟,win7局域网网站开发,手机网站html模板下载**在日常开发APP的过程中#xff0c;难免需要使用第二方库和第三方库来帮助开发者快速实现一些功能#xff0c;提高开发效率。但是#xff0c;这些库也可能会给线程带来一定的压力#xff0c;主要表现在以下几个方面#xff1a;
线程数量增多#xff1a;一些库可能会在后…**在日常开发APP的过程中难免需要使用第二方库和第三方库来帮助开发者快速实现一些功能提高开发效率。但是这些库也可能会给线程带来一定的压力主要表现在以下几个方面
线程数量增多一些库可能会在后台启动一些线程来执行任务这样会增加系统中线程的数量从而导致系统资源的浪费。线程竞争一些库可能会在同一时间启动多个线程来执行任务这样会导致线程之间的竞争从而影响程序的执行效率。线程阻塞一些库可能会在执行任务时阻塞主线程从而导致程序的卡顿和响应速度变慢。
整体思路
为了解决使用第二方库和第三方库代理的线程问题我选择用下面的思路来进行线程优化
线程检测评估优化空间。线程统计收集优化范围。线程和线程池优化线程数收敛。线程栈裁剪减少线程内存。
线程的性能
熟练使用Android上的线程可以帮助你提高应用程序的性能。 本篇文章讨论了使用线程的几个方面使用UI或主线程; 应用程序生命周期和线程优先级之间的关系; 以及平台提供的帮助管理线程复杂性的方法。 在每一部分本篇都描述了潜在的陷阱以及如何避免它们的策略。
主线程
当用户启动你的应用程序时Android会创建一个新的 Linux process 以及一个执行线程。 这个main线程也称为UI线程负责屏幕上发生的一切。 了解其工作原理可以帮助你使用主线程设计你的应用程序以获得最佳性能。
内部细节
主线程具有非常简单的设计它的唯一工作就是从线程安全的工作队列中取出并执行工作块直到应用程序被终止。 框架从各个地方生成一些这些工作块。 这些地方包括与生命周期信息用户事件如输入或来自其他应用程序和进程的事件相关联的回调。 此外应用程序还可以在不使用框架的情况下显式地将工作块加入队列。
应用程序执行的任何代码块都会被绑定到一个事件回调上例如输入布局填充或绘制。 当某个时间触发一个事件时事件发生的所在线程会将事件加入到主线程的消息队列。 之后主线程可以处理该事件。
当发生动画或屏幕更新时系统试图每16ms左右执行一个工作块负责绘制屏幕以便以每秒60帧的速度平滑地渲染。 为了让系统达到这个目标一些操作必须发生在主线程上。 但是当主线程的消息队列包含太多或太耗时的任务为了让主线程能够在16ms内完成工作你应将这些任务移到工作线程中去。 如果主线程不能在16ms内完成执行的代码块则用户可能感觉到卡顿或UI响应较慢。 如果主线程阻塞大约5秒钟系统将显示“ANR”对话框允许用户直接关闭应用程序。
从主线程移除多个或耗时的任务以便它们不会干扰到平滑渲染和对用户输入的快速响应是你在应用程序中采用线程的最大原因。
线程和UI对象的引用
按照设计Android UI对象不是线程安全的。 应用程序应该在主线程上创建使用和销毁UI对象。 如果尝试修改或甚至引用除主线程之外的线程中的UI对象结果可能是异常静默失败崩溃和其他未定义的错误行为。
UI对象引用导致的问题可以划分为两种显式引用和隐式引用。
显示引用
许多非主线程上的任务在最后都会更新UI对象。 但是如果某一个线程访问视图层级中的对象可能会导致应用的不稳定性如果工作线程修改了同时被任何其他线程引用的对象属性这里都是指UI对象则结果是不可预测的。
假设一个应用程序在工作线程上直接引用UI对象。 这个UI对象可能包含对一个View的引用; 但在工作完成之前该View被从视图层次结构中删除了。 如果该引用将View对象保留在内存中并对其设置属性用户并不会看到此对象因为一旦对象的引用消失应用程序就会删除该对象。
再举另一个例子View对象被工作线程引用持有包含它们的Activity的引用。 如果该Activity被销毁了但仍有一个工作的线程直接或间接引用它 - 垃圾收集器将不会回收Activity直到该工作线程执行完成。
在某些Activity生命周期事件如屏幕旋转发生时某些线程工作可能正在运行。 系统将无法执行垃圾回收直到正在进行的工作完成。 因此在内存中可能会有两个Activity对象直到垃圾回收发生。
考虑到以上场景我们建议你的应用程序的工作线程中不应该包含对UI对象的显式引用。 避免此类引用可帮助你避免这些类型的内存泄漏同时避免线程竞争。
在所有情况下应用程序应该只在主线程上更新UI对象。 如果有多个任务希望更新实际的UI你应该制定一个策略允许多个线程交互最终将结果返回到主线程。
隐式引用
在以下代码片段中可以看到带有线程对象代码的常见设计缺陷
public class MainActivity extends Activity { // …… public class MyAsyncTask extends AsyncTask { Override protected String doInBackground(Void… params) {…} Override protected void onPostExecute(String result) {…} }}
这段代码的缺陷是将线程对象MyAsyncTask声明为一些Activity的内部类。 这种声明创建一个对Activity对象隐式引用。 因此该对象持有对Activity的引用直到线程工作完成这样会导致所引用的Activity延迟销毁。 这种延迟会给内存带来更大的压力。
解决该问题的直接解决方案是在自己的文件中定义重载类实例从而移除对Activity的隐式引用。
另一个解决方案是将AsyncTask声明为静态内部类。 这样做也可以消除隐式引用问题因为静态内部类与普通内部类不同普通内部类实例需要外部类的实例才可以实例化并且可以直接访问其包含的方法和字段。 相比之下静态内部类不需要引用外部类实例因此它不包含对外部类成员的引用。
public class MainActivity extends Activity { // …… Static public class MyAsyncTask extends AsyncTask { Override protected String doInBackground(Void… params) {…} Override protected void onPostExecute(String result) {…} }}
Android线程优化方案出发点
不能通过非UI线程对View进行操作。因为Android的UI不是安全的如果View能被不同的线程所访问或修改那么就可能在程序的执行期间产生不可预期的行为或者并发错误。使用线程时避免在循坏中使用同步因为获取和释放锁的操作代价很大。会引起CPU资源的损耗。处理多线程以及线程间通信时使用HandlerThread来操作它内部包装了Looper记得不用的时候退出/释放资源哦。当工作线程与UI线程之间通信的时候推荐使用AsyncTaskAndroid 7.0后内部任务变成串行处理不再会出现以前并行时超过任务数执行饱和策略的情况Loader可以用来代替AsyncTask的某些情况因为Loader的生命周期是独立的与Application Context有关当Activity/Fragment销毁重建时它仍然在而且它特别使用异步操作比如AsyncTaskLoader代替AsyncTask也可以实现后者的功能但是生命周期完全独立于Activity。切记Loader使用完记得销毁。当你的Service不需要交互时请使用可以自动停止的IntentService。当你希望延长BroadcastReceiver的生命周期时例如启动一个后台线程IntentService。在onReceiver中调用BroadcastReceiver.goAsync()它会返回一个PendingResult对象这时广播接收器的生命周期会延长持续到PendingResult.finish()方法调用。线程池最好用构造方法手动创建而不要用Executors来直接调用工厂方法这样利于明白线程池的运行规则避免用了错误的线程池导致资源耗尽。给线程一个好听的名字调试时候用。线程池设置线程的存活时间以保证空闲线程准确释放。
有关Android的线程优化就介绍这麽多更多的Android性能优化问题可以参考《Android性能优化》这个文档。 优化
1、 定义全局的ThreadMananger管理类通过一个全局的线程池管理一些new Thread的操作。
2、 定义线程池的时候使用final static结构定义该线程池以免该类或该方法短时间内重复调用而导致线程增多。
3、 带有定时器的性质的线程HandlerThread、Timer退出时一定要做退出或者取消操作防止内存泄漏尽可能用HandlerThread替代Timer。
4、 App实现一套符合自身业务如带有优先级的线程池。
总结
线程它就像一面双刃剑用的好的时候可以给我们带来事半功倍等效果用的不好时就会给我们带来困扰并且这个困扰还不是一时半会能解决掉的因为发现问题的时候往往是到了需要优化期了各项业务相互牵扯故在项目初期就需要严格考虑考量这些问题了。**