由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 @   nickycookie  阅读(497)  评论(2编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
点击右上角即可分享
微信分享提示