安卓多线程使用总结

定义梳理

1、Message: Message Queue中的存放的对象。
Message实例对象的取得,通常使用Message类里的静态方法obtain()。它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。
2、MessageQueue:是一种 数据 结构,是一个消息队列。
每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动 创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。
3、Looper: 是MessageQueue的管理者。
每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。
4、Handler: 消息的处理者
handler 负责将需要传递的信息封装成Message,通过调用handler 对象的obtainMessage()来实现;将消息传递给Looper,这是通过handler 对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。

线程间如何传递消息

这里分了四种情况:1、主线程给自己发消息;2、其他线程给主线程发消息;3、主线程给其他线程发送消息;4、其他线程发送消息。为每种情况,我写了一个小的demo实现其基本流程。
1、 主线程给自己发送消息
由于,主线程由系统自动为其创建Looper对象,并开启消息循环,所以,我们在主线程创建Handler对象时不需要显示创建Looper对象。
代码清单一:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        msg = (TextView) findViewById(R.id.msg);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                //Looper looper = Looper.getMainLooper();
                handler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        // TODO Auto-generated method stub
                        super.handleMessage(msg);
                        MainActivity.this.msg.setText("我是主线程的Handler,收到消息:"
                                + (String) msg.obj);
                    }
                };
                Message msg = handler.obtainMessage(1, 1, 1, "主線程發消息了");
                handler.sendMessage(msg);

            }
        });
    }

2、 其他线程给主线程发送消息
其实这里还是要用到主线程的Looper创建handler,所以只要在主线程创建好handler对象然后利用构造或者其他public方法将handler对象传递给其他线程,在其他线程中用主线程的handler发送消息。
代码清单二:
其他线程代码:

package com.example.handlerdemo;
import android.os.Handler;
import android.os.Message;

public class MyThread extends Thread {
    private Handler handler;

    public MyThread(Handler handler) {
        this.handler = handler;
    }

    @Override
    public void run() {
        Message msg = handler.obtainMessage(1, 1, 1, "其他线程发消息了");
        handler.sendMessage(msg);
    }
}

主activity的onCreate方法

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        msg = (TextView) findViewById(R.id.msg);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                //Looper looper = Looper.getMainLooper();
                handler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        // TODO Auto-generated method stub
                        super.handleMessage(msg);
                        MainActivity.this.msg.setText("我是主线程的Handler,收到消息:"
                                + (String) msg.obj);
                    }
                };
                new MyThread(handler).start();

            }
        });
    }

3、主线程给其他线程发送消息
由于要在非主线程中创建handler对象,此时就需要显式启用Looper,如果直接new handler的话会报错误:E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()
代码清单三:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new MyThread().start();
        button = (Button) findViewById(R.id.button);
        textView = (TextView) findViewById(R.id.msg);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Message message = handler.obtainMessage(1, "主线程发送消息");
                handler.sendMessage(message);

            }
        });
    }
class MyThread extends Thread {
        @Override
        public void run() {
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // TODO Auto-generated method stub
                    super.handleMessage(msg);
                    Log.i("test", "test");

                }
            };
            Looper.loop();
        }
    }

4、其他线程给自己发送消息
代码清单三:

//  class MyHandler extends Handler{
//      public MyHandler(Looper looper) {
//          super(looper);
//      }
//      @Override
//      public void handleMessage(Message msg) {
//          // TODO Auto-generated method stub
//          super.handleMessage(msg);
//          textView.setText((String)msg.obj);
//      }
//  }
    class MyThread extends Thread{
        @Override
        public void run() {
            Looper.prepare();
            handler = new Handler(){

                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == 1 && msg.obj.equals("myself")) {
                        handler = new Handler(Looper.getMainLooper()){
                            public void handleMessage(Message msg) {
                                super.handleMessage(msg);
                                textView.setText((String)msg.obj);
                            };
                        };
                        //handler = new MyHandler(Looper.getMainLooper());
                    }
                    Message message = handler.obtainMessage(1, 1, 1, "告诉主线程,我收到自己发送的消息");
                    handler.sendMessage(message);

                }
            };
            Message message = handler.obtainMessage(1,1,1,"myself");
            handler.sendMessage(message);
            Looper.loop();
        }
    }
}

安卓多线程应用场景

Android系统为了提高程序的实时响应能力,不允许在UI线程中进行耗时的操作,否则会出现ANR异常,因此必须将耗时的任务放到非UI线程中执行。Android/Java提供了很多类来帮助大家完成异步操作,比如:Thread类,Timer类,AsyncTask类,HandlerThread类,以及Executor接口。
1. 单项异步任务
场景:文件操作,如下载和拷贝文件
方案:Thread类,AsyncTask类
比较:Thread更适合执行一些不需要跟UI频繁交互的单项任务,而AsyncTask相反
2.定时执行的任务
场景:定时刷新UI
方案:“Thread + sleep”,定时器Timer
比较: Timer是由系统创建异步通知的定时器,会更加准确
3. 工作线程
场景:“生产者–消费者”模式,TCP Server端命令处理程序
方案: “Thread + condition/lock” ,HandlerThread类,线程池Executor
比较:前面的两种方式,都是“串行”的方式在执行“命令”,如果希望提供并发性,同时开启和管理多个线程来执行任务,则可以考虑使用Executor。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值