由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)。

posted @ 2013-05-12 16:18  nickycookie  阅读(497)  评论(2编辑  收藏  举报