安卓多线程使用总结
2015-07-16 16:01
381 查看
定义梳理
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。
相关文章推荐
- poj 2104 划分树模板
- java-银行业务调度系统《十一》
- valuestack,stackContext,ActionContext.之间的关系
- GRE写作必备句型
- 关于排序算法
- MyBatis学习总结(一)——MyBatis快速入门
- 安装配置openstack 中的 Open vSwitch (OVS) service
- thinkphp autoload 命名空间自定义 namespace
- jquery设置元素的readonly和disabled的写法
- [NLP]自然语言理解概述
- PHP缓存
- putchar和printf的区别,以及数组和指针的关系理解
- 进程和线程关系及区别
- hdu 1398 Square Coins(母函数)
- CentOS7 LNMP状态管理命令
- [leedcode 92] Reverse Linked List II
- hdu 1398 Square Coins(母函数)
- Bower 手册
- 跟我学数据结构之基本概念
- 复制带随机指针的链表