进程的本质:cup分别执行两处不同的指令
微指令是程序的最小单位,所以线程的分割点也只能是在微指令的切换处。
线程、looper、Message、Handerl的关系
代码
看了《深入理解android内核数据思想》和《android开发的艺术》关于"线程、hander、message、MesageQueue、looper"的讲解,总感觉理解的还是不够深入,隔靴搔痒的感觉还是有,于是用java模拟一般关于上面的知识。感觉思路立马清晰。
线程基类
public class AndroidThread extends Thread {
public AndroidThread mAndroidThread;
public Looper mLooper = null;
/**
* 获取当前线程
* @return
*/
public static AndroidThread currentThread(){
Thread thread = Thread.currentThread();
AndroidThread thread2 = (AndroidThread)thread;
return thread2;
}
/**
* 向所在的线程发消息
* @param m
*/
public void sendEmptyMessage(Message m) {
mLooper.mQueueList.add(m);
}
}
线程B
public class AndroidThreadB extends AndroidThread {
public Handler h;
public Handler h2;
AndroidThreadA mAndroidThreadA;
/**
* 运转
*/
public void run() {
Looper.prepare();
h = new Handler();
h.sendEmptyMessage(6);
h2 = new Handler(){
public void handlerMessage(Message m) {
super.handlerMessage(m);
if(m.whart==7) {
Message message = h2.creatMessage(8);
mAndroidThreadA.sendEmptyMessage(message);
}
}
};
h2.sendEmptyMessage(7);
mian();
Looper.loop();
}
/**
* 线程入口
*/
public void mian() {
mAndroidThreadA = new AndroidThreadA();
mAndroidThreadA.mAndroidThread = this;
mAndroidThreadA.start();
}
}
线程A
public class AndroidThreadA extends AndroidThread {
public Handler h;
/**
* 运转
*/
public void run() {
Looper.prepare();
h = new Handler();
h.sendEmptyMessage(5);
Looper.loop();
}
}
Handler
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.PriorityBlockingQueue;
public class Handler {
public Looper mLooper;
public LinkedList<Message> mQueueList;
public Handler() {
mLooper = Looper.myLooper();
mQueueList = mLooper.mQueueList;
}
public void handlerMessage(Message m) {
System.out.println("handlerMessage");
System.out.println("m.whart"+m.whart);
System.out.println(Thread.currentThread().getName());
System.out.println("");
}
public void sendEmptyMessage(int what) {
Message m = new Message(this);
m.whart = what;
mQueueList.add(m);
mQueueList.add(new Message(this));
}
public Message creatMessage(int what) {
Message m = new Message(this);
m.whart = what;
return m;
}
}
Looper
import java.util.LinkedList;
public class Looper {
public LinkedList<Message> mQueueList = new LinkedList<Message>();
/**
* 构造函数
*/
public Looper() {
AndroidThread thread = AndroidThread.currentThread();
Looper looper = this;
thread.mLooper = looper;
}
/**
* 准备
*/
public static void prepare() {
AndroidThread.currentThread().mLooper = new Looper();
}
/**
* 循环(静态)
*/
public static void loop() {
AndroidThread thread2 = AndroidThread.currentThread();
Looper loop = thread2.mLooper;
loop.loop2();
}
/**
* 循环
*/
public void loop2() {
while(true) {
try {
Message mes = mQueueList.getFirst();
mes.callBack();
mQueueList.remove(mes);
}catch(Exception e){
}
}
}
/**
* 获取当前线程的looper
* @return
*/
public static Looper myLooper() {
return AndroidThread.currentThread().mLooper;
}
}
Message
public class Message {
public Handler mHandler;
public int whart;
public Message(Handler handler) {
mHandler = handler;
}
public void callBack() {
mHandler.handlerMessage(this);
}
}
程序入口
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("线程模拟");
AndroidThreadB aThread = new AndroidThreadB();
aThread.start();
}
}
运行结果
线程模拟
handlerMessage
handlerMessage
m.whart6
m.whart5
Thread-0
handlerMessage
m.whart0
Thread-0
handlerMessage
m.whart7
Thread-0
handlerMessage
m.whart0
Thread-0
Thread-1
handlerMessage
m.whart0
Thread-1
handlerMessage
m.whart8
Thread-1
代码2
1.基于本人的习惯,喜欢迅速的运行起来,然后再分析代码,这里将类写到一个文件里,方面拷贝代码。
2.android关于线程的Looper用了一个ThreadLocal类来处理各线程的Looper(尽管我没弄清楚这样的意图,但还是尽量模仿一下,在我看来这样是效率低下的,但不知道android这样设计的意图在哪里)
package androidThread3;
import java.util.HashMap;
import java.util.LinkedList;
class Athread extends Thread{
public Handler mH;
public Athread mFAthread;
public void sendEmptyMessage(Message m) {
Looper looper = Looper.myLooper();
looper.mQueue.add(m);
}
}
class ThreadA extends Athread{
public void createHandler() {
mH = new Handler() {
public void handlerMessage(Message m) {
super.handlerMessage(m);
if(m.whart==1) {
main();
}
}
};
}
public void run() {
Looper.prepare();
createHandler();
mH.sendEmptyMessage(1);
Looper.loop();
}
public void main() {
ThreadB tb = new ThreadB();
tb.mFAthread = this;
tb.start();
}
}
class ThreadB extends Athread{
public void createHandler() {
mH = new Handler() {
public void handlerMessage(Message m) {
super.handlerMessage(m);
if(m.whart==2) {
Message msg = mH.creatMessage(3);
mFAthread.sendEmptyMessage(msg);
}
}
};
}
public void run() {
Looper.prepare();
createHandler();
mH.sendEmptyMessage(2);
Looper.loop();
}
}
class Looper{
public static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public MessageQueue mQueue = new MessageQueue();
public static Looper myLooper() {
Looper looper = sThreadLocal.get();
return looper;
}
public static void prepare() {
Looper looper = new Looper();
sThreadLocal.set(looper);
}
public static void loop() {
myLooper().loop2();
}
public void loop2(){
for(;;) {
Message msg = mQueue.next();
if(msg!=null) {
msg.callBack();
}
}
}
}
class Handler{
public Looper mLooper;
public MessageQueue mQueue;
public Handler() {
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;
}
public void handlerMessage(Message m) {
System.out.println("handlerMessage");
System.out.println("m.whart"+m.whart);
System.out.println(Thread.currentThread().getName());
System.out.println("");
}
public void sendEmptyMessage(int what) {
Message m = new Message(this);
m.whart = what;
mQueue.add(m);
}
public Message creatMessage(int what) {
Message m = new Message(this);
m.whart = what;
return m;
}
}
class Message{
public Handler mHandler;
public int whart;
public Message(Handler handler) {
mHandler = handler;
}
public void callBack() {
mHandler.handlerMessage(this);
}
}
class MessageQueue{
public LinkedList<Message> mQueueList = new LinkedList<Message>();
public void add(Message message) {
mQueueList.add(message);
}
public Message next() {
Message mes=null;
try {
mes = mQueueList.getFirst();
mQueueList.remove(mes);
}catch(Exception e){
}
return mes;
}
}
class ThreadLocal<T>{
public HashMap<String,T> mLoopers;
public ThreadLocal() {
mLoopers = new HashMap<String,T>();
}
public void set(T t) {
String threadName = Thread.currentThread().getName();
mLoopers.put(threadName,t);
}
public T get() {
String threadName = Thread.currentThread().getName();
T t = mLoopers.get(threadName);
return t;
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("android 线程模拟");
ThreadA ta = new ThreadA();
ta.start();
}
}
运行结果
handlerMessage
m.whart1
Thread-0
handlerMessage
m.whart2
Thread-1
handlerMessage
m.whart3
Thread-1
学习总结:
1.怎么跨进程
a.由硬件的角度看,应该是将函数的调用指令放到了不同的内存空间。
b.从现象删上看,哪里创建的回调对象(handle),在哪个线程上执行,具体原理,不清楚,可能需要分析虚拟机的原理。
2.Handelr和Message的关系:Handelr即是发消息者,也是处理消息者,这让人感觉有点困惑。为什么不直接调用呢,直接调用可以吗?还是通过如下几种情况说明吧:
handler是否跨进程的几种价值体现表
改变响应周期:将发消息和响应消息的时间拉开
跨对象调用:跨对象的消息通讯
跨线程:跨线程的消息通讯
消息的处理对象关系表
1.发送和处理的都是handler。
2.线程内Looper和MessageQueue都只有一个对象。
3.同线程内handler可以有多个,但发送到本线程的消息都发到一个消息队列中(MessageQueue)
4.Handelr可以把消息发送到其他线程的MessageQueue队列上