1. 程式人生 > >1,線程基礎

1,線程基礎

可能 重寫 font 處理 緩存 extends pub 線程終止 獨立

一,線程與進程

線程

進程中負責程序執行的執行單元,線程本身依靠程序進行運行,線程是程序中的順序控制流,只能使用分配給程序的資源和環境。

進程

執行中的程序,一個進程至少包含一個線程。

二,線程的生命周期

線程是一個動態執行的過程,它也有一個從產生到死亡的過程。下圖顯示了一個線程完整的生命周期:

技術分享圖片

1,初始化狀態

當使用new關鍵字Thread 類、其子類建立一個線程對象後,該線程對象就處於初始化狀態

2,就緒狀態

當線程對象調用了start()方法

之後,該線程就進入就緒狀態就緒狀態的線程處於就緒隊列中,要等待JVM裏線程調度器的調度。

3,運行狀態

就緒狀態的線程獲取 CPU 資源,就可以執行 run(),此時線程便處於運行狀態

4,超時等待狀態

運行狀態中的線程執行sleep()方法,此時線程進入到超時等待狀態

5,等待狀態

運行狀態中的線程執行wait()方法,此時線程進入到等待狀態

6,阻塞狀態

運行狀態中的線程遇到I/O 請求、同步代碼塊,此時線程進入到阻塞狀態

7,死亡狀態

一個運行狀態的線程完成任務或者其他終止條件發生時,該線程就切換到終止狀態

線程中有一個枚舉類型,包括了所有的線程狀態:

public enum State {
    //NEW狀態表示線程剛剛被定義,還未實際獲得資源以啟動,也就是還未調用start()方法。
    NEW,
    //RUNNABLE表示線程當前處於運行狀態,當然也有可能由於時間片使用完了而等待CPU重新的調度。
    RUNNABLE,
    //BLOCKED表示線程在競爭某個鎖失敗時被置於阻塞狀態。
    BLOCKED,
    //WAITING和TIMED_WAITING表示線程在運行中由於缺少某個條件而不得不被置於條件等待隊列,等待需要的條件或資源。
WAITING, TIMED_WAITING, //TERMINATED表示線程運行結束,當線程的run方法結束之後,該線程就會是TERMINATED狀態。 TERMINATED; }

在代碼中我們可以通過調用線程的getState()方法獲取當前線程的狀態。

二,創建線程的多種方式

1,繼承Thread類

創建一個新的類,該類繼承 Thread 類,然後創建一個該類的實例。在java.lang包中定義, 繼承Thread類必須重寫run()方法,該方法是新線程的入口點。它也必須調用 start() 方法才能執行。

/**
 * 
 * @類名稱:Thread1
 * @類描述:通過繼承Thread來實現多線程.
 * @創建人:Zender
 */
public class Thread1 extends Thread{
    @Override
    public void run() {
        System.err.println("通過繼承Thread來實現多線程.");
    }
}

其本質上是實現了 Runnable 接口的一個實例:

技術分享圖片

2,實現Runnable接口

/**
 * 
 * @類名稱:Thread2
 * @類描述:通過實現Runnable來實現多線程.
 * @創建人:Zender
 */
public class Thread2 implements Runnable{
    public void run() {
        System.err.println("通過實現Runnable來實現多線程.");
    }
}

3,通過匿名內部類的方式創建線程

匿名內部類創建的線程只會執行一次

public static void main(String[] args) {
    //第一種
    /*new Thread() {
        public void run() {
            System.out.println("thread start ..");
        };
    }.start();*/
    
    //第二種
    /*new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("thread start ..");
        }
    }).start();*/
    
    //第三種
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("runnable");
        }
    })
    }.start();
}

4,通過 Callable 和 Future 創建線程

1. 創建 Callable 接口的實現類,並實現 call() 方法,該 call() 方法將作為線程執行體,並且有返回值。

2. 創建 Callable 實現類的實例,使用 FutureTask 類來包裝 Callable 對象,該 FutureTask 對象封裝了該 Callable 對象的 call() 方法的返回值。

3. 使用 FutureTask 對象作為 Thread 對象的 target 創建並啟動新線程。

4. 調用 FutureTask 對象的 get() 方法來獲得子線程執行結束後的返回值。

/**
 * 
 * @類名稱:Thread3
 * @類描述:通過 Callable 和 Future 創建線程.
 * @創建人:Zender
 */
public class Thread3 implements Callable<Integer>{
    //該方法將作為線程執行體,並且有返回值。
    @Override
    public Integer call() throws Exception {
        int i = 100;
        System.err.println("通過 Callable 和 Future 創建線程.i=" + i);
        return i;
    }
}

TestMain.java

/**
 * 
 * @類名稱:TestMain
 * @類描述:測試
 * @創建人:Zender
 */
public class TestMain {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        Thread3 thread3 = new Thread3();
        FutureTask<Integer> ft = new FutureTask<Integer>(thread3);
        new Thread(ft).start();
        System.out.println("線程的返回值:" + ft.get());  
    }
}

技術分享圖片

4,通過定時器創建線程

不延遲的每秒鐘執行一次指定的線程

public static void main(String[] args) {
    Timer timer = new Timer();
    //Timer.schedule(TimerTask task,long delay,long period)
    //安排指定的任務(task)從指定延遲後的時間(delay)開始進行重復且固定的時間(period)執行.
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            // 實現定時任務
            System.out.println("timertask is run");
        }
    }, 0, 1000);
}

技術分享圖片

5,通過線程池創建線程

public static void main(String[] args) {
    //創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
    ExecutorService threadPool = Executors.newCachedThreadPool();
    for (int i = 0; i < 100; i++) {
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });
    }
    //關閉線程池
    threadPool.shutdown();
}

三,Thread常用方法

下表列出了Thread類的一些重要方法:

public void start()

使該線程開始執行;Java 虛擬

public void run()

如果該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作並返回。

public final void setName(String name)

改變線程名稱。

public final void setPriority(int priority)

更改線程的優先級。

public final void setDaemon(boolean on)

將該線程標記為守護線程或用戶線程。

public final void join(long millisec)

等待該線程終止的時間最長為 millis 毫秒。

public void interrupt()

中斷線程。

public final boolean isAlive()

測試線程是否處於活動狀態。

public static void yield()

暫停當前正在執行的線程對象,並執行其他線程。

public static void sleep(long millisec)

在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。

public static boolean holdsLock(Object x)

當且僅當當前線程在指定的對象上保持監視器鎖時,才返回 true。

public static Thread currentThread()

返回對當前正在執行的線程對象的引用。

public static void dumpStack()

將當前線程的堆棧跟蹤打印至標準錯誤流。

1,線程基礎