約玩原始碼中執行緒的呈現狀態,死鎖程式碼如何寫?

雲豹科技程式設計師發表於2021-12-06

在約玩原始碼中,執行緒是CPU排程和分派的基本單位,但是執行緒要想執行必須依存在約玩原始碼中,也就是說執行緒是屬於進城的,執行緒只是程式的一個實體。在約玩原始碼中執行緒都會呈現出哪些狀態呢?

執行緒狀態

1、執行緒狀態概覽

執行緒狀態:

  • NEW 尚未啟動
  • RUNNABLE 正在執行中
  • BLOCKED 阻塞的(被同步鎖或者IO鎖阻塞)
  • WAITING 永久等待狀態
  • TIMED_WAITING 等待指定的時間重新被喚醒的狀態
  • TERMINATED 執行完成

約玩原始碼中的執行緒的狀態可以使用getState()檢視,更多狀態詳情,檢視Thread原始碼,如下圖:
在這裡插入圖片描述

2、執行緒的狀態程式碼實現

2.1 NEW 尚未啟動狀態

Thread thread = new Thread() {
    @Override    public void run() {
        System.out.println(Thread.currentThread().getName());
    }};// 只宣告不呼叫start()方法,得到的狀態是NEWSystem.out.println(thread.getState()); // NEW

2.2 RUNNABLE 執行狀態

Thread thread = new Thread() {
    @Override    public void run() {
        System.out.println(Thread.currentThread().getName());
    }};thread.start();System.out.println(thread.getState()); // RUNNABLE

2.3 BLOCKED 阻塞狀態

使用synchronized同步阻塞實現,程式碼如下:

public class MyCounter {
    int counter;
    public synchronized void increase()  {
        counter++;
        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }}
MyCounter myCounter = new MyCounter();// 執行緒1呼叫同步執行緒,模擬阻塞new Thread(()-> myCounter.increase()).start();// 執行緒2繼續呼叫同步阻塞方法Thread thread = new Thread(()-> myCounter.increase());thread.start();// 讓主執行緒等10毫秒Thread.currentThread().sleep(10);// 列印執行緒2,為阻塞狀態:BLOCKEDSystem.out.println(thread.getState());

2.4 WAITING 永久等待狀態

public class MyThread extends Thread{
    @Override    public void run() {
        synchronized (MyThread.class){
            try {
                MyThread.class.wait();
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }}
Thread thread = new Thread(new MyThread());thread.start();// 主執行緒掛起200毫秒,等thread執行完成Thread.sleep(200);// 輸出WAITING,執行緒thread一直處於被掛起狀態System.out.println(thread.getState());

喚醒執行緒: 可使用 notify/notifyAll 方法,程式碼如下:

synchronized (MyThread.class) {
    MyThread.class.notify();}

使執行緒WAITING的方法:

  • Object的wait() 不設定超時時間
  • Thread.join()不設定超時時間
  • LockSupport的park()

檢視Thread原始碼可以知道Thread的join方法,底層使用的是Object的wait實現的,如下圖:
在這裡插入圖片描述

注意: 檢視Object的原始碼可知wait(),不傳遞引數,等同於wait(0),設定的“0”不是立即執行,而是無限的等待,不執行,如下圖:
在這裡插入圖片描述

2.5 TIMED_WAITING 超時等待狀態

TIMED_WAITING狀態,只需要給wait設定上時間即可,程式碼如下:public class MyThread extends Thread{
    @Override    public void run() {
        synchronized (MyThread.class){
            try {
                MyThread.class.wait(1000);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }}

呼叫程式碼還是一樣的,如下:

Thread thread = new Thread(new MyThread());thread.start();// 主執行緒掛起200毫秒,等thread執行完成Thread.sleep(200);// 輸出TIMED_WAITINGSystem.out.println(thread.getState());synchronized (MyThread.class) {
    MyThread.class.notify();}

2.6 TERMINATED 完成狀態

Thread thread = new Thread(()-> System.out.println(Thread.currentThread().getName()));thread.start();// 讓主執行緒等10毫秒Thread.currentThread().sleep(10);System.out.println(thread.getState());

死鎖

在約玩原始碼中使用sleep的時候是不釋放鎖的,所以利用這個特性我們可以很輕易的寫出死鎖的程式碼,具體的流程如圖(圖片來源於楊曉峰老師文章):
在這裡插入圖片描述

程式碼如下:

static  Object object1 = new Object();static  Object object2 = new Object();public static void main(String[] args) {
    Thread thread = new Thread(){
        @Override        public void run() {
            synchronized (object1){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (object2){
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }
    };
    Thread thread2 = new Thread(){
        @Override        public void run() {
            synchronized (object2){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (object1){
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }
    };
    thread.start();
    thread2.start();

執行上面的程式碼,約玩原始碼會處於無限等待之中。

總結

以上便是“約玩原始碼中執行緒的呈現狀態,死鎖程式碼如何寫?”的全部內容,學習執行緒並不是一蹴而就的事情,其中有很多細節需要我們熟練掌握,希望以上內容對大家有幫助。

本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2846037/,如需轉載,請註明出處,否則將追究法律責任。

相關文章