天天看點

Java Thread線程的生命周期

Java Thread線程的生命周期

概述

java.lang.Thread類包含一個靜态State枚舉,定義了線程的狀态。在任何給定的時間點,線程隻能處于以下狀态之一:

  • NEW:尚未開始執行的新建立的線程
  • RUNNABLE:正在運作或準備執行,但正在等待資源配置設定
  • BLOCKED:等待擷取螢幕鎖以進入或重新進入同步塊/方法
  • WAITING:等待其他線程執行特定操作,沒有任何時間限制
  • TIMED_WAITING:等待其他線程在指定的時間段内執行特定操作
  • TERMINATED:已完成執行
Java Thread線程的生命周期

NEW

一個已經建立但尚未啟動的線程,一直保持NEW這種狀态,直到使用start()方法啟動。

Runnable runnable = new NewState();
Thread t = new Thread(runnable);
System.out.println(t.getState());           

方法t.getState()将列印:

NEW           

RUNNABLE

建立了一個新線程并調用了該線程的start()方法時,狀态就從NEW轉變為RUNNABLE。處于RUNNABLE狀态的線程正在運作或準備運作,但它們正在等待系統的資源配置設定。

在多線程環境中,線程排程器(JVM的一部分)為每個線程配置設定固定的時間。是以,該線程會運作一段特定的時間,然後将控制權交給其他RUNNABLE線程。

Runnable runnable = new NewState();
Thread t = new Thread(runnable);
t.start();
System.out.println(t.getState());           
RUNNABLE           

BLOCKED

當線程正在等待螢幕鎖并試圖通路被其他線程鎖定的代碼段時,會進入BLOCKED狀态。

public class BlockedState {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new DemoBlockedRunnable());
        Thread t2 = new Thread(new DemoBlockedRunnable());
        
        t1.start();
        t2.start();
        
        Thread.sleep(1000);
        
        System.out.println(t2.getState());
        System.exit(0);
    }
}

class DemoBlockedRunnable implements Runnable {
    @Override
    public void run() {
        commonResource();
    }
    
    public static synchronized void commonResource() {
        while(true) {
            // Infinite loop to mimic heavy processing
            // 't1' won't leave this method
            // when 't2' try to enter this
        }
    }
}           
  1. 建立了兩個不同的線程:t1和t2;
  2. t1啟動并進入synchronized commonResource()方法;這意味着隻有一個線程可以通路它;嘗試通路此方法的所有其他後續線程将被阻止進一步執行,直到目前線程完成處理;
  3. 當t1進入這個方法時,它保持在一個無限while循環中;這隻是為了模拟有耗時長的業務處理,使所有其他線程都無法進入該方法;
  4. 當啟動t2時,它試圖進入commonResource()方法,t1已經在通路該方法,是以,t2将保持在BLOCKED狀态

調用t2.getState()将輸出:

BLOCKED           

WAITING

線程在等待其他線程執行特定操作時處于WAITING狀态。任何線程都可以通過調用以下三種方法進入這種狀态:

  • object.wait()
  • thread.join()
  • LockSupport.park()
public class WaitingState implements Runnable {
    public static Thread t1;

    public static void main(String[] args) {
        t1 = new Thread(new WaitingState());
        t1.start();
    }

    public void run() {
        Thread t2 = new Thread(new DemoWaitingStateRunnable());
        t2.start();

        try {
            t2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
    }
}

class DemoWaitingStateRunnable implements Runnable {
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
        
        System.out.println(WaitingState.t1.getState());
    }
}           
  1. 建立并啟動了t1
  2. t1建立一個t2并啟動它
  3. 當t2的處理繼續時,我們調用t2.join(),這将使t1處于WAITING狀态,直到t2完成執行

由于t1正在等待t2完成,是以我們從t2調用t1.getState():

WAITING           

TIMED_WAITING

當線程在規定的時間内等待另一個線程執行特定操作時,它處于TIMED_WAITING狀态。

  • thread.sleep(long millis)
  • wait(int timeout) 或 wait(int timeout, int nanos)
  • thread.join(long millis)
  • LockSupport.parkNanos
  • LockSupport.parkUntil
public class TimedWaitingState {
    public static void main(String[] args) throws InterruptedException {
        DemoTimeWaitingRunnable runnable= new DemoTimeWaitingRunnable();
        Thread t1 = new Thread(runnable);
        t1.start();
        
        // The following sleep will give enough time for ThreadScheduler
        // to start processing of thread t1
        Thread.sleep(1000);
        System.out.println(t1.getState());
    }
}

class DemoTimeWaitingRunnable implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
    }
}           

建立并啟動了一個線程t1,該線程進入睡眠狀态,逾時時間為5秒;t1.getState()輸出:

TIMED_WAITING           

TERMINATED

線程完成執行或異常終止時,它處于TERMINATED狀态。

public class TerminatedState implements Runnable {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new TerminatedState());
        t1.start();
        // The following sleep method will give enough time for 
        // thread t1 to complete
        Thread.sleep(1000);
        System.out.println(t1.getState());
    }
    
    @Override
    public void run() {
        // No processing in this block
    }
}           

啟動線程t1時,語句thread.sleep(1000)是為t1提供了足夠的時間來完成,是以輸出如下:

TERMINATED           

結論

了解Java中線程的生命周期,及狀态轉化的原因,是定位多線程問題的前提,也可以通過ThreadDump實時檢視到目前所有線程的執行狀态。

繼續閱讀