Thread2


五、   判斷多個線程是否都結束的兩種方法

確定所有線程是否都完成了工作的方法有很多,如可以採用類似於對象計數器的方法,所謂對象計數器,就是一個對象被引用一次,這個計數器就加1,銷燬引用就減1,如果引用數爲0,則垃圾蒐集器就會對這些引用數爲0的對象進行回收。

方法一:線程計數器

線程也可以採用計數器的方法,即爲所有需要監視的線程設一個線程計數器,每開始一個線程,在線程的執行方法中爲這個計數器加1,如果某個線程結束(在線程執行方法的最後爲這個計數器減1),爲這個計數器減1。然後再開始一個線程,按着一定的時間間隔來監視這個計數器,如是棕個計數器爲0,說明所有的線程都結束了。當然,也可以不用這個監視線程,而在每一個工作線程的最後(在爲計數器減1的代碼的後面)來監視這個計數器,也就是說,每一個工作線程在退出之前,還要負責檢測這個計數器。使用這種方法不要忘了同步這個計數器變量啊,否則會產生意想不到的後果。

方法二:使用Thread.join方法

join方法只有在線程結束時才繼續執行下面的語句。可以對每一個線程調用它的join方法,但要注意,這個調用要在另一個線程裏,而不要在主線程,否則程序會被阻塞的。

    個人感覺這種方法比較好。

    線程計數器方法演示:

複製代碼
    class ThreadCounter : MyThread
     {
        
private static int count = 0;
        
private int ms;
        
private static void increment()
         {
            
lock (typeof(ThreadCounter))  // 必須同步計數器
             {
                 count
++;
             }
         }
        
private static void decrease()
         {
            
lock (typeof(ThreadCounter))
             {
                 count
--;
             }
         }
        
private static int getCount()
         {
            
lock (typeof(ThreadCounter))
             {
                
return count;
             }
         }
        
public ThreadCounter(int ms)
         {
            
this.ms = ms;
         }
        
override public void run()
         {
             increment();
             Thread.Sleep(ms);
             Console.WriteLine(ms.ToString()
+"毫秒任務結束");
             decrease();
            
if (getCount() == 0)
                 Console.WriteLine(
"所有任務結束");
         }
     }


ThreadCounter counter1 
= new ThreadCounter(3000);
ThreadCounter counter2 
= new ThreadCounter(5000);
ThreadCounter counter3 
= new ThreadCounter(7000);

counter1.start();
counter2.start();
counter3.start();
複製代碼

    上面代碼雖然在大多數的時候可以正常工作,但卻存在一個隱患,就是如果某個線程,假設是counter1,在運行後,由於某些原因,其他的線程並未運行,在這種情況下,在counter1運行完後,仍然可以顯示出“所有任務結束”的提示信息,但是counter2和counter3還並未運行。爲了消除這個隱患,可以將increment方法從run中移除,將其放到ThreadCounter的構造方法中,在這時,increment方法中的lock也可以去掉了。代碼如:

        public ThreadCounter(int ms)
         {
            
this.ms = ms;
            increment();
         }

    運行上面的程序後,將顯示如圖2的結果。



                                                                 圖2

使用Thread.join方法演示


複製代碼
private static void threadMethod(Object obj)
{
     Thread.Sleep(Int32.Parse(obj.ToString()));
     Console.WriteLine(obj 
+ "毫秒任務結束");
}
private static void joinAllThread(object obj)
{
     Thread[] threads 
= obj as Thread[];
    
foreach (Thread t in threads)
        t.Join();
     Console.WriteLine(
"所有的線程結束");
}

static void Main(string[] args)
{
     Thread thread1 
= new Thread(threadMethod);
     Thread thread2 
= new Thread(threadMethod);
     Thread thread3 
= new Thread(threadMethod);

      thread1.Start(
3000);
      thread2.Start(
5000);
      thread3.Start(
7000);

      Thread joinThread 
= new Thread(joinAllThread);
      joinThread.Start(
new Thread[] { thread1, thread2, thread3 });

}
複製代碼

    在運行上面的代碼後,將會得到和圖2同樣的運行結果。上述兩種方法都沒有線程數的限制,當然,仍然會受到操作系統和硬件資源的限制。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章