线程间通信之Handler小实验

线程间通信之Handler小实验

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

目录

前言

  由于项目需要,今天找了一些关于线程间通信的知识看了一下,然后自己实验总结了一下,以此备忘。
  其它线程向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()之后的。

结尾

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值