目录
一、定义:
1、多线程:
线程是程序中单一的顺序控制流程,在单个程序中同时运行多个线程完成不同的工作,称为多线程。
如图:
2、ANR的三种情况:由于应用程序无响应从而出现对话框
- 主要类型按键或触摸事件在特定时间(5s)内无响应
- BroadcastReceiver在特定时间(10s)内无法处理完成
- 小概率类型Service在特定时间内无法处理完成
二、Thread类的使用方法
1、线程中的常用方法:
- start()方法:启动线程
- run()方法:不需要用户调用,继承Thread类必须重写run()方法
- sleep()方法:sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务
2、线程的状态:
- 创建(new)
- 就绪(runnable)
- 运行(running)
- 阻塞(blocked)
- time wating
- 消亡(dead)
- interrupt方法: 中断,单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常(可以用来中断一个正处于阻塞状态的线程),另外,通过interrupt方法和isInterrupted方法来停止正在运行的线程
3、上下文切换:
CPU在一个时刻只能运行一个线程,挡在云想一个线程的过程中去运行另一个线程时,叫做上下文切换。在切换时,需要保存线程的状态
代码内有解释:
//用买票来表示线程
package com.example.thread2;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
public final String TAG = "Thread2";
private Button mButton;
//线程 SaleTicket
private SaleTicket mSaleTicket;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.bt_button);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//线程开始,通过接口来设置Thread的名字
new Thread(mSaleTicket, "队伍一").start();
}
});
//传入值为10
mSaleTicket = new SaleTicket(10);
}
private class SaleTicket implements Runnable {
private int tickets = 0;
public SaleTicket(int tickets) {
this.tickets = tickets;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (tickets > 0) {
sale();
}
Log.d(TAG, "" + Thread.currentThread().getName() + ": 票卖完了");
}
private void sale() {
tickets--;
Log.d(TAG, "" + Thread.currentThread().getName() + " :买了一张票,还剩下 "
+ tickets + " 张票");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
三、线程相关组件
1)职责
1、Message:消息,其中包括了消息ID,消息处理对象以及处理的数据等。Message由MessageQueue统一队列,终由Handler处理。
2、Handler:处理者,负责Message的发送及处理。实现HandlerMessage(Message msg)方法对特定的Message进行处理。
3、MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。
4、Looper:消息泵,不断从MessageQueue中抽取Message执行。一个MessageQueue需要一个Looper。
5、Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
2)关系
1、Handler、Looper和MessageQueue是最简单的三角关系,Looper和MessageQueue是一一对应的。
2、创建一个Looper同时,会创建一个MessageQueue,Handler、Looper和MessageQueue是最简单的聚焦关系。
3、多个Handler都可以共享同一个Looper和MessageQueue了。当然这些Handler也都运行在同一个线程里。
3)消息循环
4)线程与更新
5)SDK提供了四种可以从其他线程访问UI线程:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable,long)
- Handler
6)总结
- Handler的处理过程运行在创建Handler的线程里。
- 一个Looper对应一个MessageQueue
- 一个线程对应一个Looper
- 一个Looper可以对应多个Handler
- 不确定当线程时,更新UI时尽量调用post方法
代码:
package com.example.handlerdemo;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class MainActivity extends ActionBarActivity {
private final String TAG = "Handler";
private Button mButton;
private TextView mMsgTextView;
private Handler mMainHandler;
private Handler mChildHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// init for ui
mButton = (Button) findViewById(R.id.bt_button);
mMsgTextView = (TextView) findViewById(R.id.tv_msg);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// TODO Auto-generated method stub
Message msg = mMainHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putString("name", "zhangsan");
bundle.putInt("age", 23);
msg.setData(bundle);
msg.what = 100;
msg.obj = "Hello";
//发送消息
mChildHandler.sendMessage(msg);
}
});
mMainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
String text = (String) msg.obj;
mMsgTextView.setText(text);
}
};
new ChildThread().start();
}
private class ChildThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
//初始化消息队列的参数
Looper.prepare();
mChildHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
int what = msg.what;
Bundle bundle = msg.getData();
String name = bundle.getString("name");
int age = bundle.getInt("age");
Log.d(TAG, "name = " + name + ", age = " + age);
Log.d(TAG, "what = " + what);
String text = (String) msg.obj;
text += ", World!";
Message message = mChildHandler.obtainMessage();
message.obj = text;
mMainHandler.sendMessage(message);
}
};
// 开启消息队列
Looper.loop();
}
}
}