线程间通信之Handler小实验

来源:互联网 发布:iphone序列号查询软件 编辑:程序博客网 时间:2024/04/27 19:02

线程间通信之Handler小实验

转载请标明地址,谢谢:http://blog.csdn.net/pfugwtg/article/details/50347341

目录

  • 线程间通信之Handler小实验
    • 目录
    • 前言
    • 基本知识
    • 第一段代码
      • 1这一部分代码运行后DDMS如图
      • 2退出应用后再次进入应用后DDMS变成这样
      • 3点击destroy按钮后的DDMS
      • 小结1
    • 第二段代码
      • 1程序启动后日志是空的
      • 2点击Send按钮后的Logcat
      • 小结2
    • 结尾

前言

  由于项目需要,今天找了一些关于线程间通信的知识看了一下,然后自己实验总结了一下,以此备忘。
  其它线程向UI线程传递消息之类的我就不写了,这类知识网上可以找一大堆,我这里主要是讲一下UI线程以外的线程间通讯。

基本知识

  在非UI线程中若要创建Handler,则必需调用Looper.prepare()Looper.loop(),但对于它们的具体调用时机,童鞋们又知道多少呢,嘿嘿嘿…
  好了,肉戏来了。。。

第一段代码

package com.example.androidtest.thread.communicate;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.Log;public class ThreadsCommunicate {    private static final String TAG = "ThreadsCommunicate";    private Thread aThread = null;    private Handler mHandler = null;    public ThreadsCommunicate() {        aThread = new AThread();        aThread.start();    }    public void sendMsg() {        if(null != mHandler) {            Log.d(TAG, "sendMsg success!");            mHandler.obtainMessage().sendToTarget();        }        else {            Log.e(TAG, "sendMsg failed...");        }    }    public void destroy() {        if(null != mHandler) {            mHandler.getLooper().quit();        }    }    private class AThread extends Thread {        @Override        public void run() {            this.setName("myAThread");            Looper.prepare();            Log.i(TAG, "AThread run()");            mHandler = new Handler() {                @Override                public void handleMessage(Message msg) {                    Log.i(TAG, "Thread name:" + this.getLooper().getThread().getName());                    super.handleMessage(msg);                }            };            Looper.loop();            super.run();        }    }}

调用部分代码:

package com.example.androidtest;import com.example.androidtest.thread.communicate.ThreadsCommunicate;import android.app.Activity;import android.os.Bundle;import android.view.View;public class MainActivity extends Activity{    private ThreadsCommunicate mThreadsCommunicate;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mThreadsCommunicate = new ThreadsCommunicate();    }    public void viewOnClick(View view) {        switch (view.getId()) {        case R.id.btn_send:            mThreadsCommunicate.sendMsg();            break;        case R.id.btn_destroy:            mThreadsCommunicate.destroy();            break;        default:            break;        }    }}

1、这一部分代码运行后DDMS如图:

这里写图片描述
点击Send按钮后DDMS不变,日志输出如图:
这里写图片描述

2、退出应用后再次进入应用后DDMS变成这样:

这里写图片描述
  Oh,my god!我们发现多了一个线程,这是为什么???

3、点击destroy按钮后的DDMS:

这里写图片描述
  奇迹发生了,线程少了一个!!!看到这里,我想大家已经知道原因了吧:)

小结1:

  在非UI线程中创建Handler(调用Looper.prepare()Looper.loop())后,在不需要的时候,必需调用Looper.quit()方法;否则,创建该Handler的线程将无法被释放。想想吧,如果每执行一次退出/进入程序操作就多一个线程,那最后,嘿嘿,结果你懂的。。。

第二段代码

  在这里,我们只要改一点点代码就可以了:

package com.example.androidtest.thread.communicate;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.Log;public class ThreadsCommunicate {    private static final String TAG = "ThreadsCommunicate";    private Thread aThread = null;    private Handler mHandler = null;    public ThreadsCommunicate() {        aThread = new AThread();        aThread.start();    }    public void sendMsg() {        if(null != mHandler) {            Log.d(TAG, "sendMsg success!");            mHandler.obtainMessage().sendToTarget();        }        else {            Log.e(TAG, "sendMsg failed...");        }    }    public void destroy() {        if(null != mHandler) {            mHandler.getLooper().quit();        }    }    private class AThread extends Thread {        @Override        public void run() {            this.setName("myAThread");            Looper.prepare();            Looper.loop();//嘿嘿,就是把这一行从下面移到了这儿,看看结果吧            Log.i(TAG, "AThread run()");            mHandler = new Handler() {                @Override                public void handleMessage(Message msg) {                    Log.i(TAG, "Thread name:" + this.getLooper().getThread().getName());                    super.handleMessage(msg);                }            };            super.run();        }    }}

  改动即是注释部分,结果怎样呢,我们来看看:

1、程序启动后,日志是空的!!!

  好吧,我知道你们一定不相信,肯定怀疑我的Logcat坏了,为了打破你们的幻想,我们接着看下面:

2、点击Send按钮后的Logcat

这里写图片描述
  哈哈,这下你们死心了吧,看日志就知道了:mHandler==null

小结2:

  在非UI线程中创建Handler时,创建Handler的时机必须是在Looper.prepare()Looper.loop()之间,并且所有的有效代码都必需在Looper.loop()之前;因为就实验结果来看,貌似程序是无法执行到Looper.loop()之后的。

结尾

  今天因为项目开发,所以在网上在找一些线程间通信的知识,然后自己也粗略看了一些(因为都知道个大概,但细节不确定),但还是没能解决我的一些疑惑;于是我自己动手做了这个小实验,并将实验过程以博文方式记录下来,权当对网上的其它资料的一个补充(当然,若是网上其它还有这方面的文章,那就是我粗心没看到了)。

0 0
原创粉丝点击