Java線程

什麼是線程?

線程與進程相似,但線程是一個比進程更小的執行單位。一個進程在其執行的過程中可以產生多個線程。與進程不同的是同類的多個線程共享同一塊內存空間和一組系統資源,所以系統在產生一個線程,或是在各個線程之間作切換工作時,負擔要比進程小得多,讓使用者感覺到這些線程在同時執行 ,也正因爲如此,線程也被稱爲輕量級進程。

什麼是進程?

進程是程序的一次執行過程,是系統運行程序的基本單位,因此進程是動態的。系統運行一個程序即是一個進程從創建,運行到消亡的過程。簡單來說,一個進程就是一個執行中的程序,它在計算機中一個指令接着一個指令地執行着,同時,每個進程還佔有某些系統資源如CPU時間,內存空間,文件,文件,輸入輸出設備的使用權等等。換句話說,當程序在執行時,將會被操作系統載入內存中。

線程和進程有什麼不同?

線程是進程劃分成的更小的運行單位。線程和進程最大的不同在於基本上各進程是獨立的,而各線程則不一定,因爲同一進程中的線程極有可能會相互影響。從另一角度來說,進程屬於操作系統的範疇,主要是同一段時間內,可以同時執行一個以上的程序,而線程則是在同一程序內幾乎同時執行一個以上的程序段。

如何創建線程:

1.繼承Thread類創建線程:
1)定義Thread類的子類,並重寫該類的run()方法,該方法的方法體就是線程需要完成的任務,run()方法也稱爲線程執行體。
2)創建Thread子類的實例,也就是創建了線程對象
3)啓動線程,即調用線程的start()方法

public class TestThread01 {
    public static void main(String[] args) {
       MyThread thread = new MyThread();
       thread.start();
    }
}

class MyThread extends Thread{
    private static int num = 0;
    public MyThread(){
        num++;
    }
    @Override
    public  void run(){
        System.out.println("主動創建創建的第"+num+"線程");
    }
}

2.實現Runnable接口創建線程:(推薦實現Runnable接口方式開發多線程,因爲Java單繼承但是可以實現多個接口。
1)定義Runnable接口的實現類,一樣要重寫run()方法,這個run()方法和Thread中的run()方法一樣是線程的執行體
2)創建Runnable實現類的實例,並用這實例作爲Thread的target來創建Thread對象,這個Thread對象纔是真正的線程對象
3)第三部依然是通過調用線程對象的start()方法來啓動線程
注意,這種方式必須將Runnable作爲Thread類的參數,然後通過Thread的start方法來創建一個新線程來執行該子任務。如果調用Runnable的run方法的話,是不會創建新線程的,這跟普通的方法調用沒有任何區別。

public class TestThread02 {
    public static void main(String[] args)  {
        System.out.println("主線程ID:"+Thread.currentThread().getId());
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

class MyRunnable implements Runnable{
    public MyRunnable() {}

    @Override
    public void run() {
        System.out.println("子線程ID:"+Thread.currentThread().getId());
    }}

3)使用Callable和Future創建線程:
1)具體是創建Callable接口的實現類,並實現clall()方法。
2)並使用FutureTask類來包裝Callable實現類的對象,且以此FutureTask對象作爲Thread對象的target來創建線程。
注意:Callable與Runnable十分相似,但是是有返回值的。Callable接口是一個參數化的類型,只有一個call方法。

public class TestThread03 {
    public static void main(String[] args) {
       Callable<Integer> myCallable = new MyCallable();//創建一個mycallable的對象
       FutureTask<Integer> futureTask = new FutureTask<Integer>(myCallable);//使用FutureTask來包裝MyCallable對象
       for (int i = 0 ; i < 100 ; i++){
           System.out.println(Thread.currentThread().getName() + "  " + i);
           if (i == 30){
               Thread thread = new Thread(futureTask);
               thread.start();
           }
       }

        System.out.println("主線程for循環執行完畢!");

        try{
            int sum = futureTask.get();
            //MyCallable中sum的返回值:4950會永遠最後輸出,原因在於通過futureTask.get()方法獲取子線程call()方法的返回值時,
            // 當子線程此方法還未執行完畢,futureTask.get()方法會一直阻塞,直到call()方法執行完畢才能取到返回值。
            System.out.println("MyCallable中sum的返回值:" + sum);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

class MyCallable implements Callable<Integer>{

    private int sum = 0;

    @Override//與Runnable重寫run()方法不同色是,call()方法是有返回值的
    public Integer call() throws Exception {
        for (int i = 0 ; i < 100 ; i++){
            System.out.println(Thread.currentThread().getName() + i);
            sum += i;
        }
        return  sum;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章