一、認識多線程中的 start() 和 run() 1。start(): 先來看看Java API中對於該方法的介紹: 使該線程開始執行;Java 虛擬機調用該線程的 run 方法。 結果是兩個線程併發地運行;當前線程(從調用返回給 start 方法)和另一個線程(執行其 run 方法)。 多次啟動 ...
一、認識多線程中的 start() 和 run()
1。start():
先來看看Java API中對於該方法的介紹:
使該線程開始執行;Java 虛擬機調用該線程的
run
方法。結果是兩個線程併發地運行;當前線程(從調用返回給
start
方法)和另一個線程(執行其run
方法)。多次啟動一個線程是非法的。特別是當線程已經結束執行後,不能再重新啟動。
用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體中的代碼執行完畢而直接繼續執行後續的代碼。通過調用Thread類的 start()方法來啟動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這裡的run()方法 稱為線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。
2。run():
同樣先看看Java API中對該方法的介紹:
如果該線程是使用獨立的
Runnable
運行對象構造的,則調用該Runnable
對象的run
方法;否則,該方法不執行任何操作並返回。
Thread
的子類應該重寫該方法。run()方法只是類的一個普通方法而已,如果直接調用Run方法,程式中依然只有主線程這一個線程,其程式執行路徑還是只有一條,還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下麵的代碼,這樣就沒有達到寫線程的目的。
3。總結:
調用start方法方可啟動線程,而run方法只是thread類中的一個普通方法調用,還是在主線程里執行。
二、代碼實例:
1 2 3 4 5 6 7 8 9 10 11 12 13 public
static
void
main(String args[]) {
Thread t =
new
Thread() {
public
void
run() {
pong();
}
};
t.start();
System.out.print(
"ping"
);
}
static
void
pong() {
System.out.print(
"pang"
);
}
輸出結果: pingpang
1 2 3 4 5 6 7 8 9 10 11 12 13 public
static
void
main(String args[]) {
Thread t =
new
Thread() {
public
void
run() {
pong();
}
};
t.run();
System.out.print(
"ping"
);
}
static
void
pong() {
System.out.print(
"pang"
);
}
輸出結果:pongpang
通過以上兩個程式實例,可以很容易的區分出start()方法和run()方法的區別:
t.start(); 該行代碼相當於是啟動線程,
t.run(); 該行代碼相當於是使用t這個類中的run方法而已.
三、線程狀態說明:
線程狀態從大的方面來說,可歸結為:初始狀態、可運行狀態、不可運行狀態和消亡狀態,具體可細分為上圖所示7個狀態,說明如下:
1)線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable介面,但不管怎樣,當我們new了Thread實例後,線程就進入了初始狀態;
2)當該對象調用了start()方法,就進入可運行狀態;
3)進入可運行狀態後,當該對象被操作系統選中,獲得CPU時間片就會進入運行狀態;
4)進入運行狀態後涉及的情況就比較多,大致有如下情形: ﹒run()方法或main()方法結束後,線程就進入終止狀態; 當線程調用了自身的sleep()方法或其他線程的join()方法,就會進入阻塞狀態(該狀態雖停止當前線程,但並不釋放所占有的資源)。當sleep()結束或join()結束後,該線程進入可運行狀態,繼續等待OS分配時間片; 當線程剛進入可運行狀態(註意,還沒運行),發現將要調用的資源被鎖住(synchroniza,lock),將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池裡也許已經有了其他線程在等待獲取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記後,就轉入可運行狀態,等待OS分配 CPU時間片; 當線程調用wait()方法後會進入等待隊列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態後,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個線程,但我們由於不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒後會進入鎖池,等待獲取鎖標記。 當線程調用stop方法,即可使線程進入消亡狀態,但是由於stop方法是不安全的,不鼓勵使用,大家可以通過run方法里的條件變通實現線程的 stop。
安全終止線程的自定義方法:
public class SafeStopThread implements Runnable{
//定義線程終止的開關
private volatile boolean stop=false;//此變數必須加上volatile
int a=0;
@Override
public void run() {
// TODO Auto-generated method stub
while(!stop){
synchronized ("") {
a++;
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
a--;
String tn=Thread.currentThread().getName();
System.out.println(tn+":a="+a);
}
}
//線程終止方法
public void threadStop(){
stop=true;
}
public static void main(String[] args) {
SafeStopThread t=new SafeStopThread();
Thread t1=new Thread(t);
t1.start();
for(int i=0;i<5;i++){
new Thread(t).start();
}
t.threadStop();//改變終止線程的狀態
}
}線程安全終止:https://blog.csdn.net/lexang1/article/details/49819347