Java線程:建立與啓動
1、定義線程
一、擴展java.lang.Thread類。
此類中有個run()方法,應該注意其用法:
public void run()
-
若是該線程是使用獨立的
Runnable
運行對象構造的,則調用該
Runnable
對象的
run
方法;不然,該方法不執行任何操做並返回。
-
Thread
的子類應該重寫該方法。
二、實現java.lang.Runnable接口。
void
run()
-
使用實現接口
Runnable
的對象建立一個線程時,啓動該線程將致使在獨立執行的線程中調用對象的
run
方法。
-
方法
run
的常規協定是,它可能執行任何所需的操做。
2、實例化線程
一、若是是擴展java.lang.Thread類的線程,則直接new便可。
二、若是是實現了java.lang.Runnable接口的類,則用Thread的構造方法:
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
3、啓動線程
在線程的Thread對象上調用start()方法,而不是run()或者別的方法。
在調用start()方法以前:線程處於新狀態中,新狀態指有一個Thread對象,但尚未一個真正的線程。
在調用start()方法以後:發生了一系列複雜的事情
啓動新的執行線程(具備新的調用棧);
該線程重新狀態轉移到可運行狀態;
當該線程得到機會執行時,其目標run()方法將運行。
注意:對Java來講,run()方法沒有任何特別之處。像main()方法同樣,它只是新線程知道調用的方法名稱(和簽名)。所以,在Runnable上或者Thread上調用run方法是合法的。但並不啓動新的線程。
4、例子
一、實現Runnable接口的多線程例子
/**
* 實現Runnable接口的類
*
* @author leizhimin 2008-9-13 18:12:10
*/
public
class DoSomething
implements Runnable {
private String name;
public DoSomething(String name) {
this.name = name;
}
public
void run() {
for (
int i = 0; i < 5; i++) {
for (
long k = 0; k < 100000000; k++) ;
System.out.println(name +
": " + i);
}
}
}
/**
* 測試Runnable類實現的多線程程序
*
* @author leizhimin 2008-9-13 18:15:02
*/
public
class TestRunnable {
public
static
void main(String[] args) {
DoSomething ds1 =
new DoSomething(
"阿三");
DoSomething ds2 =
new DoSomething(
"李四");
Thread t1 =
new Thread(ds1);
Thread t2 =
new Thread(ds2);
t1.start();
t2.start();
}
}
執行結果:
李四: 0
阿三: 0
李四: 1
阿三: 1
李四: 2
李四: 3
阿三: 2
李四: 4
阿三: 3
阿三: 4
Process finished with exit code 0
二、擴展Thread類實現的多線程例子
/**
* 測試擴展Thread類實現的多線程程序
*
* @author leizhimin 2008-9-13 18:22:13
*/
public
class TestThread
extends Thread{
public TestThread(String name) {
super(name);
}
public
void run() {
for(
int i = 0;i<5;i++){
for(
long k= 0; k <100000000;k++);
System.out.println(
this.getName()+
" :"+i);
}
}
public
static
void main(String[] args) {
Thread t1 =
new TestThread(
"阿三");
Thread t2 =
new TestThread(
"李四");
t1.start();
t2.start();
}
}
執行結果:
阿三 :0
李四 :0
阿三 :1
李四 :1
阿三 :2
李四 :2
阿三 :3
阿三 :4
李四 :3
李四 :4
Process finished with exit code 0
對於上面的多線程程序代碼來講,輸出的結果是不肯定的。其中的一條語句for(long k= 0; k <100000000;k++);是用來模擬一個很是耗時的操做的。
5、一些常見問題
一、線程的名字,一個運行中的線程老是有名字的,名字有兩個來源,一個是虛擬機本身給的名字,一個是你本身的定的名字。在沒有指定線程名字的狀況下,虛擬機總會爲線程指定名字,而且主線程的名字老是mian,非主線程的名字不肯定。
二、線程均可以設置名字,也能夠獲取線程的名字,連主線程也不例外。
三、獲取當前線程的對象的方法是:Thread.currentThread();
四、在上面的代碼中,只能保證:每一個線程都將啓動,每一個線程都將運行直到完成。一系列線程以某種順序啓動並不意味着將按該順序執行。對於任何一組啓動的線程來講,調度程序不能保證其執行次序,持續時間也沒法保證。
五、當線程目標run()方法結束時該線程完成。
六、一旦線程啓動,它就永遠不能再從新啓動。只有一個新的線程能夠被啓動,而且只能一次。一個可運行的線程或死線程能夠被從新啓動。
七、線程的調度是JVM的一部分,在一個CPU的機器上上,實際上一次只能運行一個線程。一次只有一個線程棧執行。JVM線程調度程序決定實際運行哪一個處於可運行狀態的線程。
衆多可運行線程中的某一個會被選中作爲當前線程。可運行線程被選擇運行的順序是沒有保障的。
八、儘管一般採用隊列形式,但這是沒有保障的。隊列形式是指當一個線程完成「一輪」時,它移到可運行隊列的尾部等待,直到它最終排隊到該隊列的前端爲止,它才能被再次選中。事實上,咱們把它稱爲可運行池而不是一個可運行隊列,目的是幫助認識線程並不都是以某種有保障的順序排列唱呢個一個隊列的事實。
九、儘管咱們沒有沒法控制線程調度程序,但能夠經過別的方式來影響線程調度的方式。