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

  • 相关阅读:
    chrome 等浏览器不支持本地ajax请求的问题
    3:1 类型转换
    WebService-WSDL简单介绍
    WebService—CXF整合Spring实现接口发布和调用过程
    WebService—CXF—实现接口发布和客户端调用
    WebService—规范介绍和几种实现WebService的框架介绍
    (转)c# 扩展方法
    (转)C# Textbox的ImeMode取值对中文输入法的影响
    (转)Nandflash读写
    (转+整理)Nandflash存储
  • 原文地址:https://www.cnblogs.com/cqcmdwym/p/3074138.html
Copyright © 2020-2023  润新知