前篇說到了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線程繼續列印!
但是結果不盡人意呀,結果很是驚訝的!運作結果:
好吧,開始列印,列印到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