线程通信原理之一:线程本地存储(TLS)

定义

Thread Local Storage (TLS) is the method by which each thread in a given multithreaded process can allocate locations in which to store thread-specific data. (https://msdn.microsoft.com/en-us/library/6yh4a9k1.aspx)。翻译过来,就是说一个TLS变量能在多个线程中保持相应的分身,每个线程能访问属于自己的那个分身,而对别的线程的分身无权访问(好像不是翻译。。。)。Android中的TLS类型的数据结构是ThreadLocal,它的实现就是用一个各线程共享的key-value映射数组,key是线程号,value是变量值,这样,每个线程就有对应的变量值了。 


Looper
Looper有一个静态的ThreadLocal类型的数据结构sThreadLocal,用来存储Looper对象。因为sThreadLocal是静态的,所以它为同一个进程中的所有的线程所共享。定义如下:
static final ThreadLocal<Looper> sThreadLocal = newThreadLocal<Looper>();
一个线程默认是没有自己的Looper的,它若想要使用Looper,需要在Thread的入口函数里面先调用Looper.prepare(),新创建一个Looper,并插入到sThreadLocal中,即在其中插入一个键值对;而Looper.myLooper()是拿属于自己这个线程的Looper,调用了sThreadLocal.get()。最后还需要调用Looper.loop()去循环处理mQueue中的消息。真正的处理需要调用msg.target.dispatchMessage,它是调用的这个Looper所位于的Handler内部的handlerMessage函数来处理消息。
final MessageQueue mQueue;
private static void prepare(boolean quitAllowed) {
sThreadLocal.set(new Looper(quitAllowed));
}
public static void loop() {
        final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
            Message msg = queue.next();
   msg.target.dispatchMessage(msg);
...
}
}
public static Looper myLooper() {
        return sThreadLocal.get();
    }
入口函数代码:
publicvoid run() {  
synchronized(mLock) {  
Looper.prepare();  
mLooper= Looper.myLooper();  
mLock.notifyAll();  
}  
Looper.loop();  

}


Handler
Handler是由某个线程创建的,但是由于线程共享进程空间,因此其他线程也可以访问到这个Handler。这是Handler起作用的基础。
在Handler的构造函数中
public Handler(Callback callback, boolean async) {
……
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
……
    }
所以Handler是线程相关的,这个线程就是mLooper属于的线程,也是创造Handler的线程,也是Handler处理事情即调用handleMessage的线程。
向某个Handler发message需要调用sendMessage,最后会调到queue.enqueueMessage。向Handler发Runnable需要调用post。若handler是个Handler,那么handler.sendMessage(msg)就是往handler的queue里填充消息,其实就是给这个handler发消息。而handler.obtainMessage就是在消息池里拿消息,设置这个消息的target为handler。
题外话:
Handler中有个函数是runWithScissors,这个函数定义如下:
public final boolean runWithScissors(final Runnable r, long timeout) {
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }
        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
}


怎么理解呢?看注释:
If the current thread is the same as the handler thread, then the runnable runs immediately without being enqueued.  Otherwise, posts the runnable to the handler and waits for it to complete before returning.
对照看代码,在当前线程和创建Handler的线程是一个线程的时候,直接运行runnable,否则,把runnable放入Handler的消息队列中,当前线程wait直到runnable运行完毕。


示例代码

1.	private static class Worker implementsRunnable {  
2.	        privatefinal Object mLock = new Object();  
3.	        privateLooper mLooper;  
4.	         
5.	        /** 
6.	         * Createsa worker thread with the given name. The thread 
7.	         * thenruns a {@link android.os.Looper}. 
8.	         * @paramname A name for the new thread 
9.	         */  
10.	        Worker(Stringname) {  
11.	            Threadt = new Thread(null, this, name);  
12.	           t.setPriority(Thread.MIN_PRIORITY);  
13.	           t.start();  
14.	            synchronized(mLock) {  
15.	                while(mLooper == null) {  
16.	                   try {  
17.	                       mLock.wait();  
18.	                   } catch (InterruptedException ex) {  
19.	                   }  
20.	                }  
21.	            }  
22.	        }  
23.	         
24.	        publicLooper getLooper() {  
25.	            returnmLooper;  
26.	        }  
27.	         
28.	        publicvoid run() {  
29.	            synchronized(mLock) {  
30.	               Looper.prepare();  
31.	                mLooper= Looper.myLooper();  
32.	                mLock.notifyAll();  
33.	            }  
34.	            Looper.loop();  
35.	        }  
36.	         
37.	        publicvoid quit() {  
38.	            mLooper.quit();  
39.	        }  
40.	    }  
41.	   
42.	   
43.	package com.example.test;  
44.	   
45.	import android.app.Activity;  
46.	import android.graphics.Bitmap;  
47.	import android.os.Bundle;  
48.	import android.os.Handler;  
49.	import android.os.Looper;  
50.	import android.os.Message;  
51.	import android.view.View;  
52.	import android.widget.ProgressBar;  
53.	import android.widget.TextView;  
54.	   
55.	public classProgressTestActivity extends Activity {  
56.	    privateProgressBar progress;  
57.	    private TextView text;  
58.	    private Worker mWorker;  
59.	    privateWorkerHandler mWorkerHandler;  
60.	    private UIHandlermUIHandler;  
61.	   
62.	    @Override  
63.	    public void onCreate(BundlesavedInstanceState) {  
64.	        super.onCreate(savedInstanceState);  
65.	        setContentView(R.layout.activity_main);  
66.	        progress =(ProgressBar) findViewById(R.id.progressBar1);  
67.	        text =(TextView) findViewById(R.id.textView1);  
68.	        mWorker = new Worker("artworker");  
69.	        mWorkerHandler = newWorkerHandler(mWorker.getLooper());  
70.	        mUIHandler = newUIHandler(Looper.myLooper());  
71.	    }  
72.	   
73.	    public voidstartProgress(View view) {  
74.	        Message msgObj = mWorkerHandler.obtainMessage();  
75.	        msgObj.what = 2;  
76.	        mWorkerHandler.sendMessage(msgObj);  
77.	    }  
78.	   
79.	    // Simulatingsomething timeconsuming  
80.	    private voiddoFakeWork() {  
81.	        try {  
82.	            Thread.sleep(1000);  
83.	        } catch(InterruptedException e) {  
84.	            e.printStackTrace();  
85.	        }  
86.	    }  
87.	   
88.	    private static class Worker implements Runnable{  
89.	        private final Object mLock = new Object();  
90.	        private Looper mLooper;  
91.	   
92.	        /** 
93.	         * Creates a worker thread with the given name.The thread then runs a 
94.	         * {@link android.os.Looper}. 
95.	         * 
96.	         * @param name 
97.	         *           A name for the new thread 
98.	         */  
99.	        Worker(String name) {  
100.	            Thread t = new Thread(null, this, name);  
101.	            t.setPriority(Thread.MIN_PRIORITY);  
102.	            t.start();  
103.	            synchronized (mLock) {  
104.	                while (mLooper == null) {  
105.	                    try {  
106.	                        mLock.wait();  
107.	                    } catch(InterruptedException ex) {  
108.	                    }  
109.	                }  
110.	            }  
111.	        }  
112.	   
113.	        public LoopergetLooper() {  
114.	            return mLooper;  
115.	        }  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值