由Android Looper的实现引发的基础补习
Android的Looper只允许一个线程中有且只有一个Looper,具体实现使用了ThreadLocal来达到这个目的,如果要在新的线程中进行消息传递,则必须调用Looper的静态方法prepare()
public class Looper { // 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象 private static final ThreadLocal sThreadLocal = new ThreadLocal(); // Looper内的消息队列 final MessageQueue mQueue; // 当前线程 Thread mThread; // 。。。其他属性 // 每个Looper对象中有它的消息队列,和它所属的线程 private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); } // 我们调用该方法会在调用线程的TLS中创建Looper对象 public static final void prepare() { if (sThreadLocal.get() != null) { // 试图在有Looper的线程中再次创建Looper将抛出异常 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } // 其他方法 }
于是在想,类变量如果是static的(比如int,初始为0),在main和子线程中各创建一个实例后打印这个int值,到底是怎么样的呢(大家有时有没有同样的感觉,可能以前真没想到这么多,或者突然之间质疑自己以前以为的结论?)
class Program { static void Main(string[] args) { Entity entity = new Entity(); entity.Print(); new Thread(t => { Entity e = new Entity(); e.Print(); }).Start(); new Thread(t => { Entity e = new Entity(); e.Print(); }).Start(); Entity entity2 = new Entity(); entity2.Print(); Entity entity3 = new Entity(); entity3.Print(); Console.Read(); } } public class Entity { private static int count = 0; public Entity() { count++; } public void Print() { Console.WriteLine(Thread.CurrentThread.ManagedThreadId+ ":" + count); } }
输出:
9:1
9:2
9:3
10:4
11:5
如果替换成ThreadLocal又会是怎么样的呢
class Program { static void Main(string[] args) { Entity entity = new Entity(); entity.Print(); new Thread(t => { Entity e = new Entity(); e.Print(); }).Start(); new Thread(t => { Entity e = new Entity(); e.Print(); }).Start(); Entity entity2 = new Entity(); entity2.Print(); Entity entity3 = new Entity(); entity3.Print(); Console.Read(); } } public class Entity { private static ThreadLocal<int> threadLocal = new ThreadLocal<int>(); public Entity() { if (threadLocal.IsValueCreated) { threadLocal.Value = threadLocal.Value + 1; } else { threadLocal.Value = 0; } } public void Print() { //Console.WriteLine(Thread.CurrentThread.ManagedThreadId+ ":" + count); Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + threadLocal.Value); } }
输出
9:0
9:1
9:2
10:0
11:0
可见不同线程中的值各有一个副本,同一线程中类似于上例中的结果(纯Static)。