首頁 > 軟體

一篇文章掌握Java Thread的類及其常見方法

2022-03-02 16:00:38

一,Thread 的幾個常見屬性

Thread 類是 JVM 用來管理執行緒的一個類,換句話說,每個執行緒都有一個唯一的 Thread 物件與之關聯。

Java中建立執行緒

顯示繼承Thread,重寫run方法來指定執行緒執行的程式碼

匿名內部類來繼承Thread,重寫run方法來指定執行緒執行的程式碼

顯示實現Runnable介面,重寫run方法

匿名內部類來繼承Runnable介面,重寫run方法

通過lambda表示式來描述執行的程式碼

屬性獲取方法
IDgetId()
名稱getNmame()
狀態getState()
優先順序getPriority()
是否後臺執行緒isDaemon()
是否存活isAlive()
是否被中斷isInterrupted()

ID 是執行緒的唯一標識,不同執行緒不會重複

名稱是各種偵錯工具用到 狀態表示執行緒當前所處的一個情況,下面我們會進一步說明

優先順序高的執行緒理論上來說更容易被排程到

關於後臺執行緒,需要記住一點:JVM會在一個程序的所有非後臺執行緒結束後,才會結束執行。

是否存活,即簡單的理解,為 run 方法是否執行結束了

執行緒的中斷問題,下面我們進一步說明

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread("123"){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++){
                    System.out.println(Thread.currentThread().getName());
                    try{
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("執行緒退出");
            }
        };
 
        //這一組屬性,執行緒建立完成後,屬性就不變了
        System.out.println(t.getName());
        System.out.println(t.getPriority());
        System.out.println(t.isDaemon());
        System.out.println(t.getId());
        //這組屬性會隨著執行緒的執行而開始改變
        System.out.println(t.isAlive());
        System.out.println(t.isInterrupted());
        System.out.println(t.getState());
 
        t.start();
 
        while (t.isAlive()){
            System.out.println("123 正在執行");
            System.out.println(t.getState());
            System.out.println(t.isInterrupted());
            Thread.sleep(300);
        }
    }

二,執行緒偵錯

1,啟動一個執行緒

之前我們已經看到了如何通過覆寫 run 方法建立一個執行緒物件,但執行緒物件被建立出來並不意味著執行緒就開始執行了。

覆寫 run 方法是提供給執行緒要做的事情的指令清單

執行緒物件可以認為是把 李四、王五叫過來了

而呼叫 start() 方法,就是喊一聲:”行動起來!“,執行緒才真正獨立去執行了。

 static class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("我是一個執行緒");
        }
    }
 
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
    }

2,中斷一個執行緒

中斷讓一個程式結束,結束可能有兩種情況

        1,已經把任務執行完了

        2,任務執行到一半,被強制結束

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
               while (! isQuit){
                   System.out.println("正在轉賬");
                   try {
                       Thread.sleep(500);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
                System.out.println("轉賬終止");
            }
        };
        t.start();
        Thread.sleep(500);
        System.out.println("有內鬼,終止交易");
        isQuit = true;
    
}

public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(){
            @Override
            public void run() {
                while (!Thread.interrupted()){
                    System.out.println("正在轉賬");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
                System.out.println("轉賬終止");
            }
        };
        t.start();
        Thread.sleep(5000);
        System.out.println("有內鬼,終止交易");
        t.interrupt();
    }

thread 收到通知的方式有兩種:

1. 如果執行緒因為呼叫 wait/join/sleep 等方法而阻塞掛起,則以 InterruptedException 異常的形式通 知,清除中斷標誌

        當出現 InterruptedException 的時候, 要不要結束執行緒取決於 catch 中程式碼的寫法. 可以選擇 忽略這個異常, 也可以跳出迴圈結束執行緒.

2.否則,只是內部的一箇中斷標誌被設定,thread 可以通過

        Thread.interrupted() 判斷當前執行緒的中斷標誌被設定,清除中斷標誌

        Thread.currentThread().isInterrupted() 判斷指定執行緒的中斷標誌被設定,不清除中斷標誌

這種方式通知收到的更及時,即使執行緒正在 sleep 也可以馬上收到。

public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++){
                    System.out.println(Thread.interrupted());
                }
            }
        };
        t.start();
        t.interrupt();
    }

public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++){
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }
        };
        t.start();
        t.interrupt();
    }

3,等待一個執行緒

t1與t2序列執行

 public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++){
                    System.out.println("我是執行緒1");
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
 
 
        Thread t2 = new Thread(){
            @Override
            public void run() {
               for (int i = 0; i < 10; i++){
                   System.out.println("我是執行緒2");
                   try {
                       Thread.sleep(50);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
            }
        };
 
 
        t1.start();
        t1.join();
        t2.start();
        t2.join();
        System.out.println("主執行緒執行完畢");
    }

t1與t2並行執行

public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++){
                    System.out.println("我是執行緒1");
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
 
 
        Thread t2 = new Thread(){
            @Override
            public void run() {
               for (int i = 0; i < 10; i++){
                   System.out.println("我是執行緒2");
                   try {
                       Thread.sleep(50);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
            }
        };
 
 
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("主執行緒執行完畢");
    }

4,休眠執行緒

public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(1000);
        System.out.println(System.currentTimeMillis());
    }

1,如果執行緒在正常執行計算判斷邏輯,此時就是在就緒佇列中排隊,排程器就會從就緒佇列中篩選出合適的PCB讓他在CPU上執行

2,如果某個執行緒呼叫sleep就會讓對應的執行緒的PCB進入阻塞佇列,阻塞佇列無法在PCB上執行

3,時間到了之後,就自動把這個PCB拿回到原來的就緒佇列中

到此這篇關於一篇文章掌握Java Thread的類及其常見方法的文章就介紹到這了,更多相關Java Thread內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com