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

一,Thread 的幾個常見屬性

Thread 類是 JVM 用來管理線程的一個類,換句話說,每個線程都有一個唯一的 Thread 對象與之關聯。

Java中創建線程

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

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

顯示實現Runnable接口,重寫run方法

匿名內部類來繼承Runnable接口,重寫run方法

通過lambda表達式來描述執行的代碼

屬性 獲取方法
ID getId()
名稱 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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: