总体思想就是两个(多个)线程共享一块存储区域,它们并发地操作这块内存。
下面是我自己初步写的模拟程序。
这里仅贴上Hander, HandlerThread, Looper2
01
package com.zte.liu;
02
03
public class Handler {
04
05
private Looper2 looper = null;
06
07
public Handler(Looper2 looper){
08
this.looper = looper;
09
}
10
11
public Message obtainMessage(){
12
return new Message(this);
13
}
14
15
public Message obtainMessage(int id){
16
return new Message(id, this);
17
}
18
19
public void dispatchMsg(Message msg){
20
handleMessage(msg);
21
}
22
23
public Looper2 getLooper(){
24
return looper;
25
}
26
27
public void handleMessage(Message msg){//钩子函数
28
System.out.println(msg.getId());
29
}
30
}
1
public class HandlerThread implements Runnable{
2
public void run(){
3
Looper2.prepare();
4
Looper2.loop();
5
}
6
}
01
package com.zte.liu;
02
03
public class Looper2 {
04
05
private static Looper2 looper = null;
06
private MessageQueue<Message> mQueue;
07
08
private Looper2(){
09
mQueue = new MessageQueue();
10
}
11
12
public static void prepare(){
13
if(looper == null){
14
looper = new Looper2();
15
}
16
}
17
18
public static Looper2 myLooper(){
19
prepare();
20
return looper;
21
}
22
23
public MessageQueue<Message> getQueue(){
24
return mQueue;
25
}
26
27
public static final void loop(){
28
System.out.println("loop begin...");
29
Looper2 looper = myLooper();
30
MessageQueue<Message> queue = looper.mQueue;
31
if(looper == null) {
32
return;
33
}
34
while(true){
35
System.out.println("----queue size ="+queue.size());
36
try {
37
Thread.sleep(1000);
38
} catch (InterruptedException e) {
39
e.printStackTrace();
40
}
41
Message msg = (Message)queue.next();
42
if(msg != null){
43
if(msg.getHandler() == null)return;
44
else{
45
msg.getHandler().dispatchMsg(msg);
46
Message.recycle(msg);
47
}
48
}
49
}
50
}
51
}
既然是这个机制是多线程操作的,就要多用用线程的概念。
准备知识:
1. obj.notify() 与 obj.wait()
分别表示:
释放等待队列中等待在obj对象上的线程;
当前线程因需要等待obj对象而进入等待队列
2. ThreadLocal类,知道其get()与set(obj)方法的含义。
参考源码jdk1.5:
总体思路:
每个线程都有一个ThreadLocalMap。
当调用ThreadLocal.set(value)时,取出当前线程的ThreadLocalMap,然后map.set(ThreadLocal对象,value);
当调用ThreadLocal.get()时,取出当前线程的ThreadLocalMap,然后return map.get(ThreadLocal对象);
源码:
01
public class ThreadLocal<T> {
02
03
private final int threadLocalHashCode = nextHashCode();
04
05
private static int nextHashCode = 0;
06
private static final int HASH_INCREMENT = 0x61c88647;
07
08
private static synchronized int nextHashCode() {
09
int h = nextHashCode;
10
nextHashCode = h + HASH_INCREMENT;
11
return h;
12
}
13
14
15
public ThreadLocal() {
16
}
17
18
19
public T get() {
20
Thread t = Thread.currentThread();
21
ThreadLocalMap map = getMap(t);
22
if (map != null)
23
return (T)map.get(this);
24
25
// Maps are constructed lazily. if the map for this thread
26
// doesn't exist, create it, with this ThreadLocal and its
27
// initial value as its only entry.
28
T value = initialValue();
29
createMap(t, value);
30
return value;
31
}
32
33
34
public void set(T value) {
35
Thread t = Thread.currentThread();
36
ThreadLocalMap map = getMap(t);
37
if (map != null)
38
map.set(this, value);
39
else
40
createMap(t, value);
41
}
42
43
44
ThreadLocalMap getMap(Thread t) {
45
return t.threadLocals;
46
}
47
48
49
void createMap(Thread t, T firstValue) {
50
t.threadLocals = new ThreadLocalMap(this, firstValue);
51
}
52
53
.......
54
55
56
static class ThreadLocalMap {
57
58
........
59
60
}
61
62
}
最后看看改进的ThreadHandler和Looper类
01
package com.zte.liu;
02
03
public class HandlerThread extends Thread{
04
05
private Looper mLooper;
06
07
public void run(){
08
Looper.prepare();
09
synchronized(this){//本身线程会对mLooper存储区域做写操作,故需要放置临界区
10
mLooper = Looper.myLooper();
11
this.notifyAll();//通知等待在this对象上的线程走出等待队列
12
}
13
Looper.loop();
14
}
15
16
public Looper getLooper(){//其他线程会对mLooper存储区域做读操作,故需要放置临界区
17
if(!isAlive()){
18
return null;
19
}
20
//if the thread has been started, wait until the looper has been created.
21
synchronized(this){
22
while(isAlive() && mLooper==null){
23
try {
24
this.wait();//当前线程因等待this对象而进入等待队列
25
} catch (InterruptedException e) {
26
e.printStackTrace();
27
}
28
}
29
}
30
return mLooper;
31
}
32
33
}
01
package com.zte.liu;
02
03
import com.zte.liu.*;
04
05
public class Looper{
06
07
private static final ThreadLocal sThreadLocal = new ThreadLocal();
08
private MessageQueue<Message> mQueue;
09
10
private Looper(){
11
mQueue = new MessageQueue<Message>();
12
}
13
public synchronized static final void prepare(){
14
if(sThreadLocal.get() != null){
15
throw new RuntimeException("sThreadLocal already contains looper object");
16
}
17
sThreadLocal.set(new Looper());
18
}
19
20
public static final void loop(){
21
System.out.println("loop begin...");
22
Looper looper = myLooper();
23
MessageQueue<Message> queue = looper.mQueue;
24
if(looper == null) {
25
return;
26
}
27
while(true){
28
System.out.println("----queue size ="+queue.size());
29
try {
30
Thread.sleep(1000);
31
} catch (InterruptedException e) {
32
e.printStackTrace();
33
}
34
Message msg = (Message)queue.next();
35
if(msg != null){
36
if(msg.getHandler() == null)return;
37
else{
38
msg.getHandler().dispatchMsg(msg);
39
Message.recycle(msg);
40
}
41
}
42
}
43
}
44
public static Looper myLooper(){
45
return (Looper)(sThreadLocal.get());
46
}
47
public MessageQueue<Message> getQueue(){
48
return mQueue;
49
}
50
51
}