您的位置:首页 > 其它

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

2015-05-09 17:10 330 查看
定义

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.	        }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: