说明:本系列文章是从《有心课堂》中”谷歌的小弟”之《深入探讨Android异步精髓Handler》教程整理。 Handler是Android中对消息的一种处理机制,处理说到底是对数据的处理,特别是在多线程中,我们要保证各个线程中的数据不相互干涉就要用到ThreadLocal类。 ThreadLocal类是不同线程的数据副本。我们可以举例说明。人都有很多身份,就以我做例子,在公司是职员,回到家是儿子,在女朋友面前是男朋友。下面写个程序来询问身份。
PRivate String mString; //身份记录private String res1, res2, res3; //几个场景:公司、家、女朋友面前写两个线程询问本人的身份。
/** * 我在公司 */private class Thread01 extends Thread{ @Override public void run() { setString("我是职员"); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } res1 = getString(); }}/** * 我在家 */private class Thread02 extends Thread{ @Override public void run() { setString("我是儿子"); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } res2 = getString(); }}现在来打印身份:
public class ThreadLocalActivity01 extends Activity{ private String mString; private String res1, res2, res3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); askWhoAreYou(); } private void askWhoAreYou(){ new Thread01().start(); new Thread02().start(); setString("我是男朋友"); res3 = getString(); try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Log.i("我在公司", res1); Log.i("我在家", res2); Log.i("我在女朋友面前", res3); } public void setString(String string) { mString = string; } public String getString() { return mString; }}运行看看角色:
几次运行结果不相同,角色乱了,所以需要用ThreadLocal来解决此类问题。
public class ThreadLocalActivity02 extends Activity{ private String res1, res2, res3; private ThreadLocal<String> mThreadLocal = new ThreadLocal<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); askWhoAreYou(); } private void askWhoAreYou(){ new Thread01().start(); new Thread02().start(); mThreadLocal.set("我是男朋友"); res3 = mThreadLocal.get(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Log.i("我在公司", res1); Log.i("我在家", res2); Log.i("我在女朋友面前", res3); } private class Thread01 extends Thread{ @Override public void run() { mThreadLocal.set("我是职员"); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } res1 = mThreadLocal.get(); } } private class Thread02 extends Thread{ @Override public void run() { mThreadLocal.set("我是儿子"); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } res2 = mThreadLocal.get(); } }}我们首先创建一个ThreadLocal的对象,在每个场景(线程)中设置自己的身份。
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }通过源码我们可以很清晰看到身份设置时会利用场景(即当前线程)做Map的Key,这样就保证了每个线程对应的Key不同所以值互不影响。在多线程的情况,就是靠着这样的实现保证不同线程中处理的消息互不影响。
新闻热点
疑难解答