開始一個執行緒兩種方式的區別
java 開始一個現成有兩中方法 :一是直接呼叫Thread例項的start()方法,二是將Runable例項傳給一個Thread例項然後呼叫它的start()方法。
首先讓我們看看Thread類的start() 方法:
public synchronized void start() {
if (started)
throw new IllegalThreadStateException();
started = true;
group.add(this);
start0();
}
一個Thread的例項一旦呼叫了start() 方法,這個例項的started標記就標記為true,不管這個執行緒是否給執行,只要呼叫了一次start()就再也沒有機會運行了.這意味著:通過Thread的start() 方法,一個Thread只能生成一個執行緒.所以下面的程式碼會丟擲異常:
public class Test { public static void main(String[] args) throws Exception{ MyThread mt = new MyThread(); mt.start(); mt.join();//線上程物件a上呼叫join()方法,就是讓當前正在執行的執行緒等待執行緒物件a對應的執行緒執行完成後才繼續執行 Thread.sleep(3000); mt.start(); } }
當執行緒物件mt執行完成後,我們讓主執行緒休息一下,然後我們再次在這個執行緒物件上啟動執行緒。結果我們看到:
Exception in thread "main" java.lang.IllegalThreadStateException
如果要讓一個例項產生多個執行緒,著就要使用Runnable 藉口的功能了.
如果我們把一個Runnable例項給Thread物件多次包裝,我們就可以看到它們實際是在同一例項上啟動執行緒:
class R implements Runnable{ private int x = 0; public void run(){ for(int i=0;i<100;i++){ try{ Thread.sleep(10); }catch(Exception e){} System.out.println(x++); } } }
public class Test { public static void main(String[] args) throws Exception{ R r = new R(); for(int i=0;i<10;i++) new Thread(r).start(); } }
x 是例項變數,但結果是x被加到了999,說明這10個執行緒是在同一個r物件上執行的.
但是如果使用Thread 來使用執行緒:
class MyThread extends Thread{
public int x = 0;
public void run(){
for(int i=0;i<100;i++){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(x++);
}
}
}
public class Test {
public static void main(String[] args) throws Exception{
for(int i=0;i<10;i++)
new MyThread ().start();
}
}
x例項變數被建立了10次,每個現程建立了一次,每個x都是加到了10.不像Runnable 物件,每個現成都共享同一個Runnable 物件,共享同一個例項變x.
我們把上面用Runnable 方式建立的執行緒,同一例項(Runnable例項)的多個執行緒。
從dev2dev網友axman的go deep into java專欄文件,結合自己的總結而來.