在"線程系列04,傳遞數據給線程,線程命名,線程異常處理,線程池"中,我們已經知道,每個進程都有一個線程池。可以通過TPL,ThreadPool.QueueUserWorkItem,委托與線程池交互。本篇體驗:通過查看CLR代碼來觀察線程池及其線程。
□ 通過編碼查看線程池和線程
使用ThreadPool的靜態方法QueueUserWorkItem把線程放入線程池,來看線程池線程和主程序線程的執行情況。
class Program{static void Main(string[] args){Console.WriteLine("主線程開始");for (int i = 0; i < 5; i++){ThreadPool.QueueUserWorkItem(SayHello, i);}Console.WriteLine("主線程結束");}static void SayHello(object arg){int n = (int) arg;Console.WriteLine("線程{0}接收到的參數是:{1},是否是後台線程:{2}",Thread.CurrentThread.ManagedThreadId,n,Thread.CurrentThread.IsBackground);}}
○ 用QueueUserWorkItem方法加入線程池的線程是後台線程
○ 一旦主線程結束,後台線程隨即結束
○ 在主程序for語句塊中,有2個線程已被創建並執行
讓主線程和線程池線程都Sleep一段時間。
class Program{static Random r = new Random();static void Main(string[] args){Console.WriteLine("主線程開始");for (int i = 0; i < 5; i++){ThreadPool.QueueUserWorkItem(SayHello, i);}Thread.Sleep(r.Next(250, 500));Console.WriteLine("主線程結束");}static void SayHello(object arg){Thread.Sleep(r.Next(250, 500));int n = (int) arg;Console.WriteLine("線程{0}接收到的參數是:{1},是否是後台線程:{2}",Thread.CurrentThread.ManagedThreadId,n,Thread.CurrentThread.IsBackground);}}
○ 線程池中的線程依然是後台線程
○ 讓主線程Sleep一段時間後,線程池的線程在主線程結束之前得以執行
再讓主線程Sleep更長的一段時間。
static void Main(string[] args){Console.WriteLine("主線程開始");for (int i = 0; i < 5; i++){ThreadPool.QueueUserWorkItem(SayHello, i);}Thread.Sleep(r.Next(1000, 3000));Console.WriteLine("主線程結束");}
當主線程Sleep的時間更長後,線程池有更多的線程被執行。
□ 使用"即時窗口"查看CLR中的線程池和線程
以上,通過編碼查看線程池和線程,實在是太不方便。我們可以在"即時窗口"中,借助"SOS調試擴展"來觀察CLR中的線程池和線程。
→在"Thread.Sleep(r.Next(1000, 3000))"打上斷點
→點擊"啟動"
→當代碼運行到斷點處,點擊"調試"--"窗口"--"即時",打開"即時窗口"
→輸入如下命令,加載"SOS調試擴展"
關於"SOS調試擴展"的使用,可參考"調試查看CLR運行代碼"。
→輸入如下命令,查看線程池
○ Worker Thread顯示當前線程池中的線程狀況
○ Work Request in Queue顯示當前隊列中的線程
→輸入如下命令,查看所有線程
○ MTA (Finalizer)表示由GC回收的線程
○ MTA (Threadpool Worker) 表示線程池中的線程
□ 查看CLR托管堆上的所有線程類型
→輸入如下命令查看CLR托管堆上的所有線程類型
□ 查看CLR托管堆上線程池實例
→找到System.ThreadPoolWorkQueue,復制其前面的MT代碼
→輸入如下命令,查看線程池實例的堆地址、數量等
□ 查看CLR托管線程池地址
→復制System.Threading.ThreadPoolWorkQueue的托管堆地址
→輸入如下命令查看CLR托管線程池地址內容
線程系列包括:
Map map=Thread.getAllStackTraces();
System.out.println(map.size());
把這兩句話放在需要的方法裡裡,運行就可以得到結果了。
下面這句話是java api的解釋:
Thread類。
getAllStackTracespublic static Map<Thread,StackTraceElement[]> getAllStackTraces()返回所有活動線程的堆棧跟蹤的一個映射。映射鍵是線程,而每個映射值都是一個 StackTraceElement 數組,該數組表示相應 Thread 的堆棧轉儲。返回的堆棧跟蹤的格式都是針對 getStackTrace 方法指定的。
在調用該方法的同時,線程可能也在執行。每個線程的堆棧跟蹤僅代表一個快照,並且每個堆棧跟蹤都可以在不同時間獲得。如果虛擬機沒有線程的堆棧跟蹤信息,則映射值中將返回一個零長度數組。
如果有安全管理器,則通過 RuntimePermission("getStackTrace") 權限和 RuntimePermission("modifyThreadGroup") 權限調用其 checkPermission 方法,查看是否可以獲得所有線程的堆棧跟蹤。
希望以上信息對你有幫助。
用Thread.CurrentThreadState()這個方法獲得每個線程的信息
在函數體內寫對線程的控制。