安卓线程初步(一)
重要的话写在前面,关于线程知识的掌握,一定要看源码!一定要看源码!一定要看源码!一定要看源码!一定要看源码!
主要有三个java
类之间的关系一定要理解清楚:Looper
,Handler
和MessagesQueue
,这三个类之间一一对应,看了源码才知道Google设计的精妙之处,不然写代码只知其然不知其所以然。本文先讲讲’其然’,’所以然’之后细说。
基本概念
进程(Process)
是一块包含了某些资源的内存区域。
进程中所包含的一个或多个执行单元为线程(Thread)
。
标准的解释如上所属,但是概念很难被理解。通俗地说,进程和线程最大的区别在于,进程是一块独立的内存空间,而线程运行在公共的内存空间中。
具体来说,每个应用都至少会开辟自己的一个进程,一个进程内可以包含多个线程。重要的是,线程可以做进程做的任何任务,所以线程可以当作“轻量级”的进程。一般来说线程处理一些小任务,“重量级”的任务会交给进程。
而且,进程之间是独立的,一个进程内的多个线程是共享内存的。所以线程间就可以共同处理一块数据,线程间的通讯比进程间的通讯容易很多。
打个比方,进程就好比一棵大树,线程就是这颗树上的树枝,所有树枝共享根部提供的养分(内存)。进程是个大工厂,线程是工厂内具体进行操作的工人。
在安卓应用程序中,主线程用于接收用户的输入,以及反馈结果。因为一旦主线程阻塞,程序就会暂停运行。所以一些会产生阻塞的操作,比如从网络上下载数据,就会放在worker thread中进行。主线程之外(worker thread)不允许修改UI属性,但是processing bar除外。
从Worker Thread到Main Thread传送数据
从Worker Thread
到Main Thread
传送数据一般用于从网络中获取数据,然后显示在界面反馈给用户。主要有三个操作步骤:
- 继承
Thread
类,使用worker thread
获取网络中的数据,发送message
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyThread extends Thread{
public void run() {
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//实用s模拟网络中获取的数据
System.out.println("MyThreadMessage------>" + Thread.currentThread().getName());
String s = "Data from internet!";
Message msg = handler.obtainMessage();
msg.obj = s;
handler.sendMessage(msg);
}
}
在workthread
实现过程中,先休眠两秒,模拟网络中获取数据的时间开销。然后创建msg
对象,把handler
和msg
对象相关联,s
的值赋给msg
,最后用handler
发送消息。
- 实现监听窗口,调用
worker thread
1
2
3
4
5
6
7
8
9
10
11
12
13
class OnButtonClick implements View.OnClickListener {
public void onClick(View view) {
//当用户点击按钮时,穿件一个消息对象,并实用Handler发送该对象
System.out.println("OnClickListener");
// Message msg = handler.obtainMessage();
// msg.what = 2;
// handler.sendMessage(msg);
Thread t = new MyThread();
t.start();
}
}
当用户点击按钮时,监听器监听到这一行为,开启一个worker thread
- 继承
Handler
类,实现handlemassges
方法获取msg
1
2
3
4
5
6
7
8
9
10
class MyHandler extends Handler{
public void handleMessage(Message msg) {
// int what = msg.what;
// System.out.println("What: " + what);
System.out.println("handleMessageThread------>" + Thread.currentThread().getName());
String s = (String)msg.obj;
textView.setText(s);
}
}
handler
位于main thread
中,故此可以修改UI为msg
传过来的消息
- 顺便附上
OnCerate()
方法
1
2
3
4
5
6
7
8
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.buttonId);
button.setOnClickListener(new OnButtonClick());
textView = (TextView) findViewById(R.id.textViewId);
handler = new MyHandler();
}
logcat中的输出
在手机上运行程序,并点击按钮。界面中的Hello world!
在两秒之后,变成Data from internet!
。
logcat中输出如下:1
2
319112-19112/com.cheryl.handler01 I/System.out: OnClickListener
19112-21361/com.cheryl.handler01 I/System.out: MyThreadMessage------>Thread-642
19112-19112/com.cheryl.handler01 I/System.out: handleMessage------>main
可见系统先是在监听器中监听到按钮被点击的行为,然后启动worker thread,最后回到main thread中修改界面。
从Main Thread到Worker Thread传送数据
- 继承
Thread
类,准备Looper
对象 - 在
Worker Thread
中生成handler
对象,重写handleMessage()
方法 - 调用
Looper.loop()
方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class WorkerThread extends Thread{
public void run() {
Looper.prepare();
System.out.println("Worker Thread");
handler = new Handler(){
// @Override
public void handleMessage(Message msg){
System.out.println("Worker thread Message received");
}
};
Looper.loop();
}
}
以上几步的使用方法在这里单独拿出来,看起来会有点别扭,但正是Google设计的巧妙之处,一个Looper
对应一个handler
一个msg
对象。
- 在
ButtonLisener
中用handler
生成msg
对象
1
2
3
4
5
6
7
8
9
10
11
class OnButtonClick implements View.OnClickListener{
public void onClick(View view) {
// MyThread t = new MyThread();
// t.start();
System.out.println("OnClickListener1");
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
System.out.println("OnClickListener2");
}
}
- 在
OnCreate
方法中启动WorkerThread
1
2
3
4
5
6
7
8
9
10
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.buttonId);
textView = (TextView) findViewById(R.id.textViewId);
WorkerThread wt = new WorkerThread();
wt.start();
button.setOnClickListener(new OnButtonClick());
}
Reference
[1] What is the difference between a process and a thread?
[2] 进程与线程的一个简单解释
[3] What is the difference between a thread and a process?