背景

项目中对于一些并不复杂的耗时操作,比如计算,不频繁操作数据库等,因为没必要使用线程池,所以之前项目会直接使用new Thread的方式,时间一长,回头再看,原来new Thread之处已经很多了,这样带来了一些问题:

  1. 不断的new Thread,损耗性能。
  2. 在有生命周期的类(Activity或者Fragment或者Service)中,有可能出现内存泄漏。
  3. 缺乏统一管理,维护不方便。

分析

问题抛出了,就想办法解决吧。对于任务量小,操作不那么频繁的,我们只需要放在一个后台线程中即能满足要求,思路是只需要分门别类就可以了,对于操作数据库的,都使用data线程,对于计算相关的,都使用background线程,这样整个项目只需要维护几个固定后台线程。

注意:

  1. data 和background都是线程的名字,可以自己添加或者定义。
  2. 因为项目中已经维护了自己封装的线程池,所有涉及到下载,请求等大量I/O操作会使用线程池。

解决方案

自己封装了ThreadManager。

  1. public class ThreadManager {
  2. /** 主线程 */
  3. public static final int THREAD_UI = 0;
  4. /** background线程,用于一般的耗时操作 */
  5. public static final int THREAD_BACKGROUND = 1;
  6. /** data线程,用于数据库操作 */
  7. public static final int THREAD_DATA = 2;
  8. private static final int THREAD_SIZE = 3;
  9. /** 线程信息数组 */
  10. private static final Handler[] HANDLER_LIST = new Handler[THREAD_SIZE];
  11. private static final String[] THREAD_NAME_LIST = {
  12. "thread_ui",
  13. "thread_background",
  14. "thread_data"
  15. };
  16. private ThreadManager() {
  17. HANDLER_LIST[THREAD_UI] = new Handler();
  18. }
  19. private static class ThreadManagerHolder {
  20. private static ThreadManager sManager = new ThreadManager();
  21. }
  22. public static ThreadManager getManager() {
  23. return ThreadManagerHolder.sManager;
  24. }
  25. /**
  26. * 派发任务
  27. *
  28. * @param index 线程类型
  29. */
  30. public void post(int index, Runnable r) {
  31. postDelayed(index, r, 0);
  32. }
  33. /**
  34. * 延迟派发任务
  35. *
  36. * @param index 线程类型
  37. */
  38. public void postDelayed(int index, Runnable r, long delayMillis) {
  39. Handler handler = getHandler(index);
  40. handler.postDelayed(r, delayMillis);
  41. }
  42. /**
  43. * 删除任务
  44. *
  45. * @param index 线程类型
  46. */
  47. public void removeCallbacks(int index, Runnable r) {
  48. Handler handler = getHandler(index);
  49. handler.removeCallbacks(r);
  50. }
  51. /**
  52. * 获取线程Handler
  53. *
  54. * @param index 线程类型
  55. */
  56. public Handler getHandler(int index) {
  57. if (index < 0 || index >= THREAD_SIZE) {
  58. throw new InvalidParameterException();
  59. }
  60. if (HANDLER_LIST[index] == null) {
  61. synchronized (HANDLER_LIST) {
  62. if (HANDLER_LIST[index] == null) {
  63. HandlerThread thread = new HandlerThread(THREAD_NAME_LIST[index]);
  64. if (index != THREAD_UI) {
  65. //优先级要低于主线程
  66. thread.setPriority(Thread.MIN_PRIORITY);
  67. }
  68. thread.start();
  69. Handler handler = new Handler(thread.getLooper());
  70. HANDLER_LIST[index] = handler;
  71. }
  72. }
  73. }
  74. return HANDLER_LIST[index];
  75. }
  76. /**
  77. * 判断是否运行在当前线程
  78. *
  79. * @param index 线程类型
  80. * @return true yes
  81. */
  82. public boolean runningOnCurrent(int index) {
  83. return getHandler(index).getLooper() == Looper.myLooper();
  84. }
  85. }

注释一目了然,不做解释。

来自:

背景

项目中对于一些并不复杂的耗时操作,比如计算,不频繁操作数据库等,因为没必要使用线程池,所以之前项目会直接使用new Thread的方式,时间一长,回头再看,原来new Thread之处已经很多了,这样带来了一些问题:

  1. 不断的new Thread,损耗性能。
  2. 在有生命周期的类(Activity或者Fragment或者Service)中,有可能出现内存泄漏。
  3. 缺乏统一管理,维护不方便。

分析

问题抛出了,就想办法解决吧。对于任务量小,操作不那么频繁的,我们只需要放在一个后台线程中即能满足要求,思路是只需要分门别类就可以了,对于操作数据库的,都使用data线程,对于计算相关的,都使用background线程,这样整个项目只需要维护几个固定后台线程。

注意:

  1. data 和background都是线程的名字,可以自己添加或者定义。
  2. 因为项目中已经维护了自己封装的线程池,所有涉及到下载,请求等大量I/O操作会使用线程池。

解决方案

自己封装了ThreadManager。

  1. public class ThreadManager {
  2. /** 主线程 */
  3. public static final int THREAD_UI = 0;
  4. /** background线程,用于一般的耗时操作 */
  5. public static final int THREAD_BACKGROUND = 1;
  6. /** data线程,用于数据库操作 */
  7. public static final int THREAD_DATA = 2;
  8. private static final int THREAD_SIZE = 3;
  9. /** 线程信息数组 */
  10. private static final Handler[] HANDLER_LIST = new Handler[THREAD_SIZE];
  11. private static final String[] THREAD_NAME_LIST = {
  12. "thread_ui",
  13. "thread_background",
  14. "thread_data"
  15. };
  16. private ThreadManager() {
  17. HANDLER_LIST[THREAD_UI] = new Handler();
  18. }
  19. private static class ThreadManagerHolder {
  20. private static ThreadManager sManager = new ThreadManager();
  21. }
  22. public static ThreadManager getManager() {
  23. return ThreadManagerHolder.sManager;
  24. }
  25. /**
  26. * 派发任务
  27. *
  28. * @param index 线程类型
  29. */
  30. public void post(int index, Runnable r) {
  31. postDelayed(index, r, 0);
  32. }
  33. /**
  34. * 延迟派发任务
  35. *
  36. * @param index 线程类型
  37. */
  38. public void postDelayed(int index, Runnable r, long delayMillis) {
  39. Handler handler = getHandler(index);
  40. handler.postDelayed(r, delayMillis);
  41. }
  42. /**
  43. * 删除任务
  44. *
  45. * @param index 线程类型
  46. */
  47. public void removeCallbacks(int index, Runnable r) {
  48. Handler handler = getHandler(index);
  49. handler.removeCallbacks(r);
  50. }
  51. /**
  52. * 获取线程Handler
  53. *
  54. * @param index 线程类型
  55. */
  56. public Handler getHandler(int index) {
  57. if (index < 0 || index >= THREAD_SIZE) {
  58. throw new InvalidParameterException();
  59. }
  60. if (HANDLER_LIST[index] == null) {
  61. synchronized (HANDLER_LIST) {
  62. if (HANDLER_LIST[index] == null) {
  63. HandlerThread thread = new HandlerThread(THREAD_NAME_LIST[index]);
  64. if (index != THREAD_UI) {
  65. //优先级要低于主线程
  66. thread.setPriority(Thread.MIN_PRIORITY);
  67. }
  68. thread.start();
  69. Handler handler = new Handler(thread.getLooper());
  70. HANDLER_LIST[index] = handler;
  71. }
  72. }
  73. }
  74. return HANDLER_LIST[index];
  75. }
  76. /**
  77. * 判断是否运行在当前线程
  78. *
  79. * @param index 线程类型
  80. * @return true yes
  81. */
  82. public boolean runningOnCurrent(int index) {
  83. return getHandler(index).getLooper() == Looper.myLooper();
  84. }
  85. }

注释一目了然,不做解释。

使用方法

注意:

在绑定生命周期的api中使用,需要主动removeCallBacks,防止内存泄漏。

结语

以上就是关于项目中一些固定线程的封装。

水平有限,如有不对之处,欢迎指出。

使用方法

注意:

在绑定生命周期的api中使用,需要主动removeCallBacks,防止内存泄漏。

结语

以上就是关于项目中一些固定线程的封装。

水平有限,如有不对之处,欢迎指出。

Android中关于项目中对Thread的管理(不是线程池)的更多相关文章

  1. Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面

    Android应用的开发过程中需要把繁重的任务(IO,网络连接等)放到其他线程中异步执行,达到不阻塞UI的效果. 下面将由浅入深介绍Android进行异步处理的实现方法和系统底层的实现原理. 本文介绍 ...

  2. Android线程管理之ExecutorService线程池

    前言: 上篇学习了线程Thread的使用,今天来学习一下线程池ExecutorService. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Execu ...

  3. 通过Thread Pool Executor类解析线程池执行任务的核心流程

    摘要:ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态. 本文分享自华为云社区<[高并发] ...

  4. Android Studio 在项目中引用第三方jar包

    在Android Studio项目中引用第三方jar包的方法: 步骤: 1.在build.gradle文件中添加如下代码: 备注:要添加在Android作用域下 sourceSets { main { ...

  5. android直接读取项目中的sqlite数据库

    最近项目中要实现android读取sqlite数据库文件,在这里先做一个英汉字典的例子.主要是输入英语到数据库中查询相应的汉语意思,将其答案输出.数据库采用sqlite3. 如图: 实现过程完全是按照 ...

  6. Android Studio修改项目中整体包名

    莫名的需求,要把之前的apk分成三个不同的apk,还要在应用市场能够上线,麻麻滴这样一听那还不要各个apk包的包名不同以及apk签名文件也不同嘛(签名文件一般也用不同,为防止上线冲突嘛).所以就亲自尝 ...

  7. ASP.NET中彩票项目中的计算复式投注的注数的方法

    从别人做的项目中抽取出的代码:

  8. jfinal想用到中大型项目中的项目经验分享

    jfinal 用在大项目中更加方便实用,节省无数的开发时间,代码量相对 SSH 减少 75% 至 90%,对于项目结构来说,简单提以下几点: 1:先分大模块,大模块内部可以根据划分的model分成子包 ...

  9. Eclipse 中 Java 项目中 .settings 文件夹作用

    今天工作时,因对 .settings 文件夹误操作,耗时 6 个多小时,才了解到原因就出在 .settings 文件夹.经查阅资料,对 .settings 做如下整理: 就如setting这个名字,就 ...

随机推荐

  1. MySQL学习笔记:regexp正则表达式

    在MySQL中,模糊搜索的时候主要用两种方式: 1.like2.regexp + 正则表达式 性能优于like 正则表达式描述了一组字符串. 最简单的正则表达式是不含任何特殊字符的正则表达式.例如,正 ...

  2. MySQL学习笔记:计算机服务中找不到MySQL服务

    不知道什么原因,连接了远程服务器之后,本地服务就连接不上. 经排查,发现服务中的MySQL服务居然不见,一番搜索之后,在CMD中进入到MySQL安装目录的bin下执行以下语句: mysqld.exe ...

  3. MySQL学习笔记:floor、round —— 取整

    在MySQL中做数值处理,需要取整或者四舍五入. floor:函数只返回整数部分,小数部分舍弃: round:函数四舍五入: END 2018-05-29 11:31:22

  4. 开源的python机器学习模块

    1. Scikit-learn Scikit-learn 是基于Scipy为机器学习建造的的一个Python模块,他的特色就是多样化的分类,回归和聚类的算法包括支持向量机,逻辑回归,朴素贝叶斯分类器, ...

  5. JAVA 转义字符串中的特殊字符

    package test; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { pu ...

  6. BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit ...

  7. bzoj 1925 dp

    思路:dp[ i ][ 0 ]表示第一个是山谷的方案,dp[ i ][ 1 ]表示第一个是山峰的方案, 我们算dp[ x ][ state ]的时候枚举 x 的位置 x 肯定是山峰, 然后就用组合数算 ...

  8. Ionic Js十一:模态

    ionicModal 可以遮住用户主界面的内容框. 你可以在你的 index 文件或者是其他文件内嵌入以下代码(里面的代码可以根据你自己的业务场景相应的改变). <script id=" ...

  9. Dijkstra算法---HDU 2544 水题(模板)

    /* 对于只会弗洛伊德的我,迪杰斯特拉有点不是很理解,后来发现这主要用于单源最短路,稍稍明白了点,不过还是很菜,这里只是用了邻接矩阵 套模板,对于邻接表暂时还,,,没做题,后续再更新.现将这题贴上,应 ...

  10. springboot+thymeleaf 模板中传递参数误报错误 红色波浪线

    在使用IDEA开发SpringBoot项目时,使用了Thymeleaf模板引擎,在使用动态传参数时,HTML页面的动态参数出现了红色波浪线,情况如下如: 解决办法: 选择 File -> Set ...