天天看點

Java中的線程Thread方法之---suspend()和resume()

前篇說到了Thread中的join方法,這一篇我們就來介紹一下suspend()和resume()方法,從字面意義上可以了解到這兩個方法是一對的,suspend()方法就是将一個線程挂起(暫停),resume()方法就是将一個挂起線程複活繼續執行。首先看一個例子:

package cn.edu.ahui;
import java.util.Iterator;  
import java.util.Map;  
import java.util.Map.Entry;  
import java.util.Set;  
  
  
/** 
 * @author weijiang204321 
 *說明: 
 *調用了suspend方法,将t0線程挂起,但是出現的問題是,t0.suspend方法之後的代碼不執行了,搞了半天終于知道為什麼了, 
 *因為在t0裡面使用了System.out.println方法了,檢視println方法的源代碼發現他是個同步的方法,加鎖了,這個鎖是哪個呢? 
 *對就是PrintStream,在Main中的printCurrentAliveThread方法中用到了System.out.println方法,打斷點才知道 
 *搞了半天阻塞在這裡了,因為我們知道suspend方法是不釋放鎖的,是以導緻會阻塞在println方法中,但是有一個前提是t0線程和main線程 
 *的println方法中拿到的是同一個鎖,這時候在看一下System.out變量時一個static PrintStream,這時候就明了了,因為是static 
 *是以對象是相同的,這兩個線程拿到的System.out是同一個對象,是以這兩個線程也是拿到的是相同的鎖的。 
 * 
 */   
public class ThreadStopLock {  
	 //列印目前線程  
	public static void printCurrentAliveThread(){  
		Map<Thread, StackTraceElement[]> maps = Thread.getAllStackTraces();  
		Set<Entry<Thread, StackTraceElement[]>> set = maps.entrySet();  
		Iterator<Entry<Thread,StackTraceElement[]>> iterator = set.iterator();  
		System.out.println("System Alive Thread List:");  
		System.out.println("-------------------------");  
		while(iterator.hasNext()){  
			System.out.println("AliveThread_Name:"+iterator.next().getKey().getName());  
		}  
		System.out.println("-------------------------");  
	}
	
	public static void main(String[] args){  
		try {  
			//定義線程  
			Thread t0 = new Thread() {  
				public void run() {  
					try { 
						for(long i=0;i<1000*1000*10;i++){  
							System.out.println(i);  
						}  
					System.out.println("thread death");  
					}catch (Throwable ex) {  
						System.out.println("Caught in run: " + ex);  
						ex.printStackTrace();  
					}  
				}  
			};  
			//開啟線程  
			t0.start();  
			//等待2s之後挂起線程t0  
			Thread.sleep(2*1000);  
			//挂起線程  
			t0.suspend();  
			//列印目前的所有線程  
			printCurrentAliveThread();  
			//等待2s之後恢複線程  
			Thread.sleep(2*1000);  
			//複活線程  
			t0.resume();  
 
		}catch (Throwable t) {  
			System.out.println("Caught in main: " + t);  
			t.printStackTrace();  
		}  
	}  
}  
           

代碼很簡單的,定義一個線程,線上程中進行列印,在主線程中的邏輯是,先開啟線程t0進行列印資料,等待2s之後将挂起線程t0,然後列印一下目前的活躍線程,然後再等待2s之後再複活t0線程繼續列印!

但是結果不盡人意呀,結果很是驚訝的!運作結果:

Java中的線程Thread方法之---suspend()和resume()

好吧,開始列印,列印到311800(當然這個不是一定的),就停止了,但是這一停止不是停2s呀,是一直停着,這不是明顯的死鎖嗎?導緻t0.suspend後面的代碼都不執行了,這就郁悶了,這個是為什麼呢?糾結了一下午,打斷點的時候才知道為什麼,斷點停在方法printCurrentAliveThread中的System.out.println()這行代碼上,那就可以斷定了,發生死鎖的原因可能就是System.out.println方法,檢視源代碼:

public void println(String x) {  
       synchronized (this) {  
           print(x);  
           newLine();  
       }  
   } 
           

這個是PrintStream對象中的println方法,是個同步鎖的方法,這時候應該就明白了,那麼這個鎖是什麼呢?沒錯,這個所就是PrintStream對象,因為在t0線程中也有System.out.println,當調用suspend()方法調用的時候,這個方法是不會釋放鎖的,當然這個鎖是同一個的,為什麼呢?看一下System類中的out變量定義:

public final static PrintStream out = null;  
           

是static類型的,是以他是類上面的鎖,肯定是同一個鎖了,是以發生了死鎖,

這時候我們将printCurrentAliveThread方法注釋之後,運作就沒有任何問題了。

就寫到這裡吧,好累,後面還有哦,繼續關注吧!

原文位址:http://blog.csdn.net/jiangwei0910410003/article/details/19910517