1. 程式人生 > >浪裡xiao白龍

浪裡xiao白龍

什麼是執行緒?

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

什麼是程序?

程序是程式的一次執行過程,是系統執行程式的基本單位,因此程序是動態的。系統執行一個程式即是一個程序從建立,執行到消亡的過程。簡單來說,一個程序就是一個執行中的程式,它在計算機中一個指令接著一個指令地執行著,同時,每個程序還佔有某些系統資源如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;
    }
}