一、任務和線程
《thinking in java》中專門有一小節中對線程和任務兩個概念進行了具體的區分,這也恰好說明任務和線程是有區別的。
正如前文所提到的,任務只是一段代碼,一段要達成你目的的代碼,這段代碼寫在哪,怎么寫其實無所謂,只是因為你希望java的多線程機制能夠識別並調用你編寫的任務,所以規定了Runnable接口,讓你的任務來實現該接口,把你想做的工作在實現該接口的run方法中實現。
那么,已經定義了任務類,那任務和線程有什么關系呢?
java的線程是用來驅動任務執行的,也就是說你得把任務掛載到一個線程上,這樣該線程才能驅動你定義的任務來執行。
二、定義線程
1.顯示的定義線程的過程就是將任務附着到線程的過程。線程Thread自身並不執行任何操作,它只是用來被多線程機制調用,並驅動賦予它的任務。
如前次文章提到的任務類定義如下:
public class Task implements Runnable { protected int countDown = 10; private static int taskCount = 0 ; private final int id = taskCount++; public Task(){} public Task(int countDown){ this.countDown = countDown; } public String status(){ return "#"+id+"("+(countDown>0?countDown:"Task!")+"). "; } @Override public void run() { while(countDown-->0){ System.out.print(status()); Thread.yield(); } } }
聲明線程並將任務附着到該線程上:
Thread t = new Thread(new Task());
這樣,任務就附着給了線程,下面就是讓線程啟動,只需要如下的調用:
t.start();
至此,線程聲明ok。
有時,我會想,是不是像任務和線程的概念分離一樣,此時只是聲明了線程,而java的線程機制並不會調用該線程運行,還需要特殊的調用才能實現多線程執行。但是下面的一段代碼告訴我,Thread類的start方法就是觸發了java的多線程機制,使得java的多線程能夠調用該線程
public static void main(String[] args){ Thread t = new Thread(new Task()); t.start(); System.out.println("Waiting for Task"); }
輸出結果如下:
Waiting for Task #0(9). #0(8). #0(7). #0(6). #0(5). #0(4). #0(3). #0(2). #0(1). #0(Task!).
先輸出“Waiting for Task”證明調用完start()方法后,立即返回了主程序,並開始執行下面的語句。而你聲明的t線程已經去被java的多線程機制調用,並驅動着它的任務運行了。
2.補充
想看到更多的線程任務運行,可以用下面的這段代碼
public static void main(String[] args){ for(int i = 0 ; i < 5 ; i++){ new Thread(new Task()).start(); } System.out.println("Waiting for Task"); }
輸出如下:
Waiting for Task #0(9). #2(9). #4(9). #0(8). #2(8). #4(8). #0(7). #2(7). #4(7). #0(6). #2(6). #4(6). #0(5). #2(5). #4(5). #0(4). #2(4). #4(4). #3(9). #2(3). #4(3). #2(2). #4(2). #2(1). #4(1). #2(Task!). #4(Task!). #1(9). #0(3). #0(2). #0(1). #0(Task!). #3(8). #1(8). #3(7). #1(7). #3(6). #1(6). #3(5). #3(4). #3(3). #3(2). #3(1). #3(Task!). #1(5). #1(4). #1(3). #1(2). #1(1). #1(Task!).
上面的輸出說明不同任務的執行在線程被換進換出時混在了一起——由線程調度器自動控制。不同版本的jdk線程調度方式不同,所以產生的結果也不相同。
這里涉及了垃圾回收器的一個問題,每個Thread都注冊了它自己,因此確實有一個對它的引用,而且在它的任務退出其run並死亡之前,垃圾回收器無法清除它。
注:以上代碼均來自《thinking in java》,內容大部分是個人理解和總結,如有錯誤請各位指正