Java多線程——<二>將任務交給線程,線程聲明及啟動


一、任務和線程

  《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》,內容大部分是個人理解和總結,如有錯誤請各位指正

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM