刚开始学一门编程语言的时候,我总是会有一种困惑,怎样让自己的代码看起来更“专业”?很多时候,我们可以照着教材实现一些基本的功能,比如用Socket发送/接收几个字符,写一个线程完成某个异步任务,但是在实际的项目中,往往不那么简单,比如需要设计Socket通信协议,需要处理Socket的连接异常断开,需要考虑在线程阻塞的情况下如何正常退出和释放资源等等,关于这些“实战经验”,前面的文章也有所涉及,以后有空准备再开个专题跟大家分享探讨一下,今天先简单地说说怎样更“专业”地在Android程序中处理多线程。

下面假设实现一个简单的定时任务,每秒钟打印一条Log信息,看看实现这样一个多线程程序,有哪些需要注意的地方,关键点都以注释的形式添加到代码中了。

package com.ticktick.testthread;import android.util.Log;public class PrintThread implements Runnable {private Thread mThread;private boolean mIsThreadStarted = false;private volatile boolean mIsThreadExit = false; //关键1:定义一个volatile类型的条件变量,用于线程的退出public void startPrintThread() { if( mIsThreadStarted ) {return;}mIsThreadExit = false;mThread = new Thread(this); //关键2:每次启动都重新创建新的Thread对象,因为一个Thread只能被start一次mThread.start();     mIsThreadStarted = true;Log.d("PrintThread", "Timer Started");}public void stopPrintThread() {if( !mIsThreadStarted ) {return;}mIsThreadExit = true; //关键3:通知线程退出循环mThread.interrupt(); //关键4:调用interrupt,防止线程内部处于sleep或者wait等阻塞状态//不过注意,对于socket.accept这样的阻塞,thread.interrupt是没有办法的,但可以用socket.close来唤醒                   try {mThread.join(1000); //关键5:调用join,等待线程真正地完成退出,建议给出一个等待超时时间}catch (InterruptedException e) {     e.printStackTrace();}mIsThreadStarted = false;Log.d("PrintThread", "Thread Stopped");}public boolean isThreadStarted() {return mIsThreadStarted;}@Overridepublic void run() {Log.d("PrintThread", "Thread Run Enter !");while( !mIsThreadExit ) {Log.d("PrintThread", "Thread Arrived !");try {Thread.sleep(1000); //关键6:线程循环中,建议使用sleep,让其他线程可以竞争CPU,sleep(0)代表立即重新竞争一次CPU}catch (InterruptedException e) {         e.printStackTrace(); //这里可以直接跳出循环,也可以忽略它而再次检查条件变量 mIsThreadExit          }        }Log.d("PrintThread", "Thread Run Exit !");}}

其实,不仅是Java线程,C/C++的多线程也应该注意这几个关键点,这里再总结一下:

(1)要定义一个volatile类型的条件变量,决定是否退出线程的死循环

(2)线程循环中,最好有sleep延时函数,让其他线程有机会竞争CPU

(3)要停止线程执行,需要做三件事,1. 置位线程退出的条件变量;2. 通过类似interrupt或者socket.close 的调用,唤醒线程中的阻塞;3. 通过join函数,等待线程真正退出,然后再释放其他相关资源

曾经在项目中,没有通过join等待线程退出,导致经常会在软件退出的时候莫名其妙地crash,因此,现在格外注意这一点,而且习惯性在线程结束的地方打印出调试信息,以保证程序中开启的所有线程都正常地销毁了。

关于线程的处理就分享到这里啦,希望对初学者有帮助,有任何疑问欢迎留言或者来信lujun.hust@gmail.com交流。

转载于:https://blog.51cto.com/ticktick/1410697

Android开发实践:以“专业”的态度处理多线程相关推荐

  1. Xamarin.Android开发实践(十七)

    Xamarin.Android开发实践(十七) 原文:Xamarin.Android开发实践(十七) Xamarin.Android之定位 一.前言 打开我们手中的应用,可以发现越来越多的应用使用了定 ...

  2. Xamarin.Android开发实践(十四)

    原文:Xamarin.Android开发实践(十四) Xamarin.Android之ListView和Adapter 一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xama ...

  3. Xamarin.Android开发实践(一)

    原文:Xamarin.Android开发实践(一) 一.准备工作 1.创建一个空的解决方案,并命名为Phoneword 2.右击解决方案 新建->新建项目 并命名为Phoneword_Droid ...

  4. Android开发实践:Java层与Jni层的数组传递

    Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni ...

  5. android并发命令,Android开发实践:基于命令模式的异步任务线程

    关于Android的异步操作,我在文章<Android开发实践:线程与异步任务>中介绍了两种方法,一种是采用线程,另一种是采用AsyncTask,今天再深入探讨下另一种模型:命令式的异步任 ...

  6. android开发实践

    # Android 开发最佳实践   从[Futurice](http://www.futurice.com)公司Android开发者中学到的经验. 遵循以下准则,避免重复发明轮子.若您对开发iOS或 ...

  7. Android开发实践:屏幕旋转的处理

    最近开发Android Camera相关的程序,被屏幕旋转搞得头大,一方面得考虑屏幕旋转后布局的变化,另一方面得搞清楚屏幕的旋转方向.角度与Camera的Preview角度的关系.本来通过重载Acti ...

  8. Android开发实践:自定义ViewGroup的onLayout()分析

    Android开发中,对于自定义View,分为两种,一种是自定义控件(继承View类),另一种是自定义布局容器(继承ViewGroup).如果是自定义控件,则一般需要重载两个方法,一个是onMeasu ...

  9. Android开发实践:线程与异步任务

    基于移动客户端的软件特别强调实时性,Android程序更是如此,任何一个程序超过5s没有响应,都会被系统强制杀掉.而且Android也不允许在UI线程中进行任何网络操作,否则就会产生NetworkOn ...

  10. android平分布局的隐藏,Android开发实践:布局的平分

    今天总结下Android开发中有关布局平分的相关技术和实现. 从一个简单的任务入手,"如何在水平方向上一左一右均匀地放置两个Button",有很多种方式可以实现这个功能,在此做一个 ...

最新文章

  1. python基本语法-Python语法基础50题
  2. 你能活多少岁,就让人工智能来告诉你吧
  3. HBase原理-要弄懂的sequenceId
  4. 蓝桥杯2015初赛-奇妙的数字
  5. 正则表达式中关于字符集的问题
  6. traceroute命令原理
  7. Mysql之七种连接查询
  8. 如何检测圣诞树? [关闭]
  9. iOS 使用Socket
  10. 用程序关闭、注销、重启计算机
  11. C#开发ActiveX控件
  12. 做软件测试三,四年后的感想
  13. 鸿蒙界境界划分,修为境界划分
  14. 模型组合方法-boosting算法详解(机器学习面试必备)
  15. 用ES6中的模板字符串实现在字符串中添加变量和字符串换行
  16. 如何确定企业是否需要推行CMMI?
  17. PMP考试关键字和黄金法则大全
  18. win8.1 android sdk,Android sdk 秒退 win8解决思路
  19. Hadoop基础(安装与启动集群)
  20. java调色板制作源码,JS实现的在线调色板实例(附demo源码下载)

热门文章

  1. arduino nano 蓝牙_探索 Golang 云原生游戏服务器开发,5 分钟上手 Nano 游戏服务器框架...
  2. 怎么彻底删除电脑上的软件_你的电脑有救了:1 个神器几个进阶方法彻底删除流氓软件!...
  3. php读取js验证码,PHP + JS 实现验证码功能
  4. 如何用eclipse操作MySQL数据库进行增删改查?
  5. fceux源码解析_fceux源码解析_从源代码制作deb包的两种方法以及修改已有deb包(转载)...
  6. 阿里云OSS上传图片实现流程
  7. 《深入理解Android:Wi-Fi,NFC和GPS》章节连载[节选]--第六章 深入理解wi-Fi Simple Configuration...
  8. opencv3 图像处理(一)图像缩放( python与c++ 实现)
  9. PHP 实现无限分类
  10. ASP.NET Aries JSAPI 文档说明:AR.Form、AR.Combobox