Java多線程start()函數和run()函數

在Java中,線程通常有五種狀態:創建,就緒,運行,阻塞和死亡。

創建狀態:在生成線程對象,並沒有調用該對象的star方法,這時線程處於創建狀態。

就緒狀態:當調用了線程對象的start方法之後,該線程就進入就緒狀態。但是此時線程調度程序還沒有把該線程設置

                爲當前線程,此時處於就緒狀態。在線程運行之後,從等待或者睡眠中回來之後,也會處於就緒狀態。

運行狀態:線程調度程序將處於就緒狀態的線程設置爲當前線程,此時線程就進入了運行狀態,開始運行run函數中的代碼。

阻塞狀態:線程正在運行的時候,被暫停 ,通常是爲了等待某個事件的發生之後再運行。sleep,suspend,wait等方法

                 都可以導致線程阻塞。

死亡狀態:如果一個線程的run方法執行結束或者被調用stop方法後,該線程就會死亡。對於死亡的線程,無法再使用start方法

               令其進入就緒。

實現線程的方法

    Java中實現並啓動線程有兩種方法:

    1.寫一個類繼承Thread類,重寫run方法,用start方法啓動線程。

    2.寫一個類實現Runnable接口,實現run方法。用new Thread(Runnable target).start()方法來啓動。

start()方法   

    用start方法來啓動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。通過調用Thread類的start()方法來啓動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這裏方法 run()稱爲線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。

run()方法

    run()方法只是類的一個普通方法而已,如果直接調用Run方法,程序中依然只有主線程這一個線程,其程序執行路徑還是隻有一條,還是要順序執行,還是要等待run方法體執行完畢後纔可繼續執行下面的代碼,這樣就沒有達到寫線程的目的。總結:調用start方法方可啓動線程,而run方法只是thread的一個普通方法調用,還是在主線程裏執行。這兩個方法應該都比較熟悉,把需要並行處理的代碼放在run()方法中,start()方法啓動線程將自動調用 run()方法,這是由jvm的內存機制規定的。並且run()方法必須是public訪問權限,返回值類型爲void。

    Thread的子類要重寫這個方法,通過Thread調用run()方法,執行線程的線程體。

調用start()後,線程會被放到等待隊列,等待CPU調度,並不一定要馬上開始執行,只是將這個線程置於可動行狀態。然後通過JVM,線程Thread會調用run()方法,執行本線程的線程體。先調用start後調用run,這麼麻煩,爲了不直接調用run?就是爲了實現多線程的優點,沒這個start不行。

多線程就是分時利用CPU,宏觀上讓所有線程一起執行 ,也叫併發

public class Test1 {
    public static void main(String[] args) {
    	ThreadTest1 t1 = new ThreadTest1();
    	ThreadTest2 t2 = new ThreadTest2();

        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.start(); 
        thread2.start();
    }
}

class ThreadTest1 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest1正在運行==========" + i);
        }
    }
}

class ThreadTest2 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest2正在運行==========" + i);
        }
    }
}

從執行結果來看,ThreadTest1和ThreadTest2是交叉執行,即併發執行的。

ThreadTest1正在運行==========0
ThreadTest2正在運行==========0
ThreadTest1正在運行==========1
ThreadTest2正在運行==========1
ThreadTest2正在運行==========2
ThreadTest2正在運行==========3
ThreadTest2正在運行==========4
ThreadTest2正在運行==========5
ThreadTest2正在運行==========6
ThreadTest2正在運行==========7
ThreadTest2正在運行==========8
ThreadTest2正在運行==========9
ThreadTest2正在運行==========10
ThreadTest2正在運行==========11
ThreadTest2正在運行==========12
ThreadTest1正在運行==========2
ThreadTest1正在運行==========3
ThreadTest1正在運行==========4
ThreadTest1正在運行==========5
ThreadTest2正在運行==========13
ThreadTest2正在運行==========14
ThreadTest2正在運行==========15
ThreadTest2正在運行==========16
ThreadTest2正在運行==========17
ThreadTest2正在運行==========18
ThreadTest1正在運行==========6
ThreadTest2正在運行==========19
ThreadTest1正在運行==========7
ThreadTest1正在運行==========8
ThreadTest1正在運行==========9
ThreadTest1正在運行==========10
ThreadTest1正在運行==========11
ThreadTest1正在運行==========12
ThreadTest1正在運行==========13
ThreadTest1正在運行==========14
ThreadTest1正在運行==========15
ThreadTest1正在運行==========16
ThreadTest1正在運行==========17
ThreadTest1正在運行==========18
ThreadTest1正在運行==========19

public class Test1 {
    public static void main(String[] args) {
    	ThreadTest1 t1 = new ThreadTest1();
    	ThreadTest2 t2 = new ThreadTest2();
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.run(); 
        thread2.run();
    }
}

class ThreadTest1 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest1正在運行==========" + i);
        }
    }
}


class ThreadTest2 implements Runnable { 
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("ThreadTest2正在運行==========" + i);
        }
    }
}

從運行結果來看,ThreadTest1和ThreadTest2是順序執行的。

ThreadTest1正在運行==========0
ThreadTest1正在運行==========1
ThreadTest1正在運行==========2
ThreadTest1正在運行==========3
ThreadTest1正在運行==========4
ThreadTest1正在運行==========5
ThreadTest1正在運行==========6
ThreadTest1正在運行==========7
ThreadTest1正在運行==========8
ThreadTest1正在運行==========9
ThreadTest1正在運行==========10
ThreadTest1正在運行==========11
ThreadTest1正在運行==========12
ThreadTest1正在運行==========13
ThreadTest1正在運行==========14
ThreadTest1正在運行==========15
ThreadTest1正在運行==========16
ThreadTest1正在運行==========17
ThreadTest1正在運行==========18
ThreadTest1正在運行==========19
ThreadTest2正在運行==========0
ThreadTest2正在運行==========1
ThreadTest2正在運行==========2
ThreadTest2正在運行==========3
ThreadTest2正在運行==========4
ThreadTest2正在運行==========5
ThreadTest2正在運行==========6
ThreadTest2正在運行==========7
ThreadTest2正在運行==========8
ThreadTest2正在運行==========9
ThreadTest2正在運行==========10
ThreadTest2正在運行==========11
ThreadTest2正在運行==========12
ThreadTest2正在運行==========13
ThreadTest2正在運行==========14
ThreadTest2正在運行==========15
ThreadTest2正在運行==========16
ThreadTest2正在運行==========17
ThreadTest2正在運行==========18
ThreadTest2正在運行==========19


實現Runnable接口所具有的優勢:

1.避免Java單繼承的問題。

2.適合多線程處理同一個資源。

3.代碼可以被多線程共享,數據獨立,很容易實現資源共享。

4.線程池只能放入實現Runable或callable類線程,不能直接放入繼承Thread的類

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章