TShopping

 找回密碼
 註冊
搜索
查看: 452|回復: 0

[教學] 由Android Looper的實現引發的基礎補習

[複製鏈接]
發表於 2017-8-24 15:19:26 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk  
Android的Looper只允許一個線程中有且只有一個Looper,具體實現使用了T​​hreadLocal來達到這個目的,如果要在新的線程中進行消息傳遞,則必須調用Looper的靜態方法prepare()

  1. public class Looper {
  2.     // 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
  3.     private static final ThreadLocal sThreadLocal = new ThreadLocal();
  4.     // Looper内的消息队列
  5.     final MessageQueue mQueue;
  6.     // 当前线程
  7.     Thread mThread;
  8.     // 。。。其他属性

  9.     // 每个Looper对象中有它的消息队列,和它所属的线程
  10.     private Looper() {
  11.         mQueue = new MessageQueue();
  12.         mRun = true;
  13.         mThread = Thread.currentThread();
  14.     }

  15.     // 我们调用该方法会在调用线程的TLS中创建Looper对象
  16.     public static final void prepare() {
  17.         if (sThreadLocal.get() != null) {
  18.             // 试图在有Looper的线程中再次创建Looper将抛出异常
  19.             throw new RuntimeException("Only one Looper may be created per thread");
  20.         }
  21.         sThreadLocal.set(new Looper());
  22.     }
  23.     // 其他方法
  24. }
複製代碼

於是在想,類變量如果是static的(比如int,初始為0),在main和子線程中各創建一個實例後打印這個int值,到底是怎麼樣的呢(大家有時有沒有同樣的感覺,可能以前真沒想到這麼多,或者突然之間質疑自己以前以為的結論?)

  1. class Program
  2.   {
  3.     static void Main(string[] args)
  4.     {
  5.       Entity entity = new Entity();
  6.       entity.Print();

  7.       new Thread(t => { Entity e = new Entity(); e.Print(); }).Start();
  8.       new Thread(t => { Entity e = new Entity(); e.Print(); }).Start();

  9.       Entity entity2 = new Entity();
  10.       entity2.Print();

  11.       Entity entity3 = new Entity();
  12.       entity3.Print();
  13.       Console.Read();
  14.     }
  15.   }

  16.   public class Entity
  17.   {
  18.     private static int count = 0;
  19.     public Entity()
  20.     {
  21.       count++;
  22.     }
  23.     public void Print()
  24.     {
  25.       Console.WriteLine(Thread.CurrentThread.ManagedThreadId+ ":" + count);
  26.     }
  27.   }
複製代碼

輸出:

9:1
9:2
9:3
10:4
11:5

如果替換成ThreadLocal又會是怎麼樣的呢

  1. class Program
  2.   {
  3.     static void Main(string[] args)
  4.     {
  5.       Entity entity = new Entity();
  6.       entity.Print();

  7.       new Thread(t => { Entity e = new Entity(); e.Print(); }).Start();
  8.       new Thread(t => { Entity e = new Entity(); e.Print(); }).Start();

  9.       Entity entity2 = new Entity();
  10.       entity2.Print();

  11.       Entity entity3 = new Entity();
  12.       entity3.Print();
  13.       Console.Read();
  14.     }
  15.   }

  16.   public class Entity
  17.   {
  18.     private static ThreadLocal<int> threadLocal = new ThreadLocal<int>();
  19.     public Entity()
  20.     {
  21.       if (threadLocal.IsValueCreated)
  22.       {
  23.         threadLocal.Value = threadLocal.Value + 1;
  24.       }
  25.       else
  26.       {
  27.         threadLocal.Value = 0;
  28.       }
  29.     }
  30.     public void Print()
  31.     {
  32.       //Console.WriteLine(Thread.CurrentThread.ManagedThreadId+ ":" + count);
  33.       Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + threadLocal.Value);
  34.     }
  35.   }
複製代碼

輸出
9:0
9:1
9:2
10:0
11:0

可見不同線程中的值各有一個副本,同一線程中類似於上例中的結果(純Static)。

 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2020-4-4 02:18 , Processed in 0.076864 second(s), 21 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表