说实话,之前在java开发的时候,很少涉及多线程的东西。由于开发的项目体量比较小,技术也比较差,所以更多的考虑的是功能,很少对并发做优化

如今借着学习Android的机会,希望可以对多线程的知识有一个更好更全面地认识。哎,感觉自己技术基础还是太差,好好加油吧

首先,安卓使用的时单线程模型:

当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。

在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。

如果在非UI线程中直接操作UI线程,会抛出android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch itsviews,这与普通的java程序不同。

由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序。

如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,因此android采用一种复杂的Message Queue机制保证线程间通信。

以上内容摘自 http://www.cnblogs.com/nio-nio/archive/2012/07/23/2604900.html,是我在网上看到的相 对比较容易理解的说明。读完以上这几段话之后,我对安卓单线程模式的理解:如果你要对UI进行操作那这些操作应该都放到主线程中;如果你要处理一些业务逻 辑或者其它的比较费时的操作,那就把这些操作放到子线程中。那因为大多数的UI更新都是基于业务逻辑的判断,如何让处理逻辑的子线程和处理UI的主线程通 信呢,这就需要用到Handler


Handler是干什么的:


Handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行。

关于Handler的使用,我们首先来看一个简单例子:

我们假设有这么一个需求:我们需要在程序中点击一个开始按钮,然后我们的程序会在后台启动一个定时任务(每隔一秒打印一个语句)。另外,我们还需要一个取消按钮,点击它终止后台的定时任务.

我们先在界面中加入两个按钮,一个开始,一个取消。接下来是activity

[java] view plaincopyprint?

  1. packagecom.example.hander1;

  2. importjava.util.Date;

  3. importandroid.app.Activity;

  4. importandroid.os.Bundle;

  5. importandroid.os.Handler;

  6. importandroid.util.Log;

  7. importandroid.view.View;

  8. importandroid.view.View.OnClickListener;

  9. importandroid.widget.Button;

  10. publicclassMainActivityextendsActivity{

  11. ButtonstartButton=null;

  12. ButtonstopButton=null;

  13. Handlerhandler=newHandler();

  14. protectedvoidonCreate(BundlesavedInstanceState){

  15. super.onCreate(savedInstanceState);

  16. setContentView(R.layout.activity_main);

  17. startButton=(Button)findViewById(R.id.startButton);

  18. stopButton=(Button)findViewById(R.id.stopButton);

  19. //为button绑定onclicklistener

  20. startButton.setOnClickListener(newButtonOnclikListener());

  21. stopButton.setOnClickListener(newButtonOnclikListener());

  22. }

  23. Runnablegoing=newRunnable(){

  24. @Override

  25. publicvoidrun(){

  26. //线程每次执行,打印日志

  27. Log.i("run","going"+newDate().getSeconds());

  28. //延时一秒钟后,再次将线程加入队列中

  29. handler.postDelayed(going,1000);

  30. }

  31. };

  32. classButtonOnclikListenerimplementsOnClickListener{

  33. @Override

  34. publicvoidonClick(Viewv){

  35. switch(v.getId()){

  36. caseR.id.startButton:

  37. begin();

  38. break;

  39. caseR.id.stopButton:

  40. stop();

  41. break;

  42. default:

  43. break;

  44. }

  45. }

  46. }

  47. //该方法将going添加到messagequeue中

  48. voidbegin(){

  49. handler.post(going);

  50. }

  51. //从messagequeue中移除going

  52. voidstop(){

  53. handler.removeCallbacks(going);

  54. }

  55. }

下面是运行结果,程序启动后是这样

当我点击启动按钮后,后台每秒中打印一条语句

当我点击取消按钮后,后台不再打印语句

对于这个程序的运行过程我是这样理解的:

1、当我点击启动按钮时:调用handler.post(going);

handler的post方法说明是这样的:Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.

也就是说,当我调用了handler.post(going);这个方法之后,handler会将我实现的Runnable对象加入到message queue中,系统会根据message queue来执行。后面一句很重要,runnable会在当前handler所属的那个线程中执行,也就是说我的going会在程序的主线程中执行,而不 是新开启的其它线程。

· 2、在going的run方法中,我调用了handler.postDelayed(going, 1000);

postDelayed这个方法和前面的post方法类似,只不过第二个参数的作用是让我的going延迟一秒钟执行。

这样其实就形成了一个死循环(我没有规定跳出的条件),程序在我点击启动之后,每隔一秒钟会在message queue中加入执行going的内容。

3、当我点击取消按钮时:调用handler.removeCallbacks(going);

虽在我在上面的写法中形成了一个死循环,但是我可以通过handler.removeCallbacks(going)这个方法,将message queue这个队列中的going去掉,这样就不再执行going了。而且根据这个方法源码中的注释:Remove any pending posts of Runnable r that are in the message queue. 应该是会把message queue中所有未执行going全部去掉。

这个程序虽然很简单,但是我在一次看到的时候,仍然陷入了误区。由于没有仔细阅读 API,我刚开始以为handler.post()这个方法会新开启一个线程。后来看到API的时候才明白原来这个程序,只有一个主线程,只不过是通过 handler将实现的Runnable 对象加入到message queue中执行的。



更多相关文章

  1. android程序---->android多线程下载(一)
  2. android 实现主线程、子线程双向通信
  3. 十大技巧优化Android(安卓)App性能
  4. Android后台线程与UI线程交互(1)
  5. 《第一行代码》学习笔记之服务
  6. Android中Handler,Looper,MessageQueue和Thread
  7. Android消息机制之HandlerThread
  8. Android入门之在子线程中更新UI
  9. Android小項目之---時間線程應用(附源碼)

随机推荐

  1. DIV水平垂直居中方法
  2. C语言用递归函数实现汉诺塔
  3. Docker 安装 PHP并与Nginx的部署实例讲解
  4. array_values()在php中返回数组的操作实
  5. 递归函数删除缓存目录,数据库简单CURD(增删
  6. PDO扩展连接mysql数据库,并实现用户登录时
  7. php中str_replace替换实例讲解
  8. php变量的8种类型 遍历php多维数组(forea
  9. 12月20日作业的作业
  10. Mac 上制作 SSL 证书