目錄
start方法和run方法
範例程式碼
注意
呼叫$yield$會讓當前行程從$Running$進入到$Runnable$就緒狀態,然後調度執行其他執行緒具體的實作依賴作業系統的任務調度器,(即當任務調度器中沒有其他任務時,即使讓出$cpu$,也會繼續執行該線程)$sleep$執行後是進入阻塞狀態,此時睡眠時間不結束,就不會分配$cpu$給該線程,但是$yield$是進入就緒狀態,即如果沒有其他線程需要執行,那麼也會給該線程分配時間片,這是$sleep$和$yield$的最大區別線程優先權
會提示調度器優先調度該線程,但它只是一個提示,調度器可以忽略他
#在沒有利用$cpu$來計算時,不要讓$while(true )$空轉浪費$cpu$,這時可以使用$yield$或$sleep$來讓$cpu$的使用權交給其他程式

interrupt方法

打断正常运行的线程,不会清空打断状态
守护线程
首頁 Java java教程 Java執行緒中的start方法和run方法怎麼使用

Java執行緒中的start方法和run方法怎麼使用

Apr 20, 2023 am 08:58 AM
java start run

    start方法和run方法

    $start()$方法用來啟動一個線程,這時此執行緒處於就緒 (可運行)狀態,並沒有運行,一旦得到$cpu$時間片,就開始執行$run()$方法。而直接呼叫$run()$方法,只是呼叫了一個類別裡的方法,其本質上還是在當前執行緒中執行的,因此只有使用$start()$方法來呼叫$run()$方法才能實現真正的多線程。

    範例程式碼

    @Slf4j(topic = "c.Test4")
    public class Test4 {
        public static void main(String[] args) {
            Thread t1 = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("running");
                }
            };
            t1.run();
        }
    }
    登入後複製

    上述程式碼是直接呼叫的$run()$方法。可以看到列印訊息裡,是$main$執行緒執行了這個方法。

    @Slf4j(topic = "c.Test4")
    public class Test4 {
        public static void main(String[] args) {
            Thread t1 = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("running");
                }
            };
            t1.start();
        }
    }
    登入後複製

    而如果使用$start()$方法啟動,才是真正的由$t1$執行緒執行的$run$方法。

    注意

    要注意的是,當$Thread$物件呼叫了$start()$方法後,就會進入就緒狀態,處於就緒狀態時無法再呼叫$start() $方法,否則就會拋出$IllegalThreadStateException$異常,如下程式碼所示

    @Slf4j(topic = "c.Test4")
    public class Test4 {
        public static void main(String[] args) {
            Thread t1 = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("running");
                }
            };
            t1.start();
            t1.start();
        }
    }
    登入後複製

    異常訊息:

    Java執行緒中的start方法和run方法怎麼使用

    ##sleep方法與yield方法

    sleep

    • 呼叫$sleep()$方法會讓目前執行緒從$Running$狀態變成$Time Waiting$狀態(阻塞)

    • 其它線程可以使用$interrupt$方法打斷正在睡眠的線程,此時$sleep$方法會拋出InterruptedException

    • ##睡眠結束後的執行緒未必會立刻得到執行
    • 建議用$TimeUnit$的$sleep$取代$Thread$的$sleep$來獲得更好的可讀性範例程式碼
    • @Slf4j(topic = "c.Test5")
      public class Test5 {
          public static void main(String[] args) {
              Thread t1 = new Thread("t1"){
                  @Override
                  public void run() {
                      try {
                          Thread.sleep(2000);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              };
              t1.start();
              log.debug("t1 state {}", t1.getState());
              //让主线程休眠500ms
              try {
                  Thread.sleep(500);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              log.debug("t1 state {}", t1.getState());
          }
      }
      //17:13:21.729 [main] DEBUG c.Test5 - t1 state RUNNABLE
      //17:13:22.245 [main] DEBUG c.Test5 - t1 state TIMED_WAITING
      登入後複製
    • 上述程式碼中,先啟動$t1$線程,此時列印執行緒的狀態應該是處於$RUNNABLE$狀態,而讓主執行緒休眠是防止主執行緒先執行列印,但還未進入到$sleep()$狀態。當執行到$run()$裡邊的$sleep$方法時,執行緒進入$TIMED WAITING$狀態
    @Slf4j(topic = "c.Test6")
    public class Thread6 {
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread("t1") {
                @Override
                public void run() {
                    try {
                        log.debug("enter sleep");
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        log.debug("wake up");
                        e.printStackTrace();
                    }
                }
            };
            t1.start();
            Thread.sleep(1000);
            log.debug("interrupt t1");
            //被唤醒
            t1.interrupt();
        }
    }
    登入後複製

    #執行結果

    Java執行緒中的start方法和run方法怎麼使用上述程式碼中,當$start$方法啟動後,$t1$線程進入睡眠狀態,列印提示訊息,睡眠時間為$2s$,在$main$線程中睡眠$1s$後打斷$t1$執行緒的睡眠,提示打斷訊息,並且呼叫$interrupt()$方法,此時執行緒被打斷,拋出異常。

    Java執行緒中的start方法和run方法怎麼使用$TimeUnit$類別中新增了以什麼單位去睡眠,可讀性更好,但是本質上沒區別,只是進行了單位換算

    TimeUnit.SECONDS.sleep(1);//该语句作用是睡眠一秒
    登入後複製

    yield

    呼叫$yield$會讓當前行程從$Running$進入到$Runnable$就緒狀態,然後調度執行其他執行緒具體的實作依賴作業系統的任務調度器,(即當任務調度器中沒有其他任務時,即使讓出$cpu$,也會繼續執行該線程)$sleep$執行後是進入阻塞狀態,此時睡眠時間不結束,就不會分配$cpu$給該線程,但是$yield$是進入就緒狀態,即如果沒有其他線程需要執行,那麼也會給該線程分配時間片,這是$sleep$和$yield$的最大區別線程優先權

    線程優先級

    會提示調度器優先調度該線程,但它只是一個提示,調度器可以忽略他

    如果$cpu$比較忙,那麼優先順序高的會獲得更多的時間片,可$cpu$空閒時,優先權幾乎沒有


    sleep的應用-防止cpu佔用100%

    #在沒有利用$cpu$來計算時,不要讓$while(true )$空轉浪費$cpu$,這時可以使用$yield$或$sleep$來讓$cpu$的使用權交給其他程式

    while (true) {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
      }
    }
    登入後複製

    可以使用$wait$或條件變數達到類似的效果

    不同的是後兩者都需要加鎖,並且需要對應的喚醒操作,一般適用於要進行同步的場景

    $sleep$適用於無需鎖定同步的場景

    join方法

    以下程式的列印結果:

    @Slf4j(topic = "c.Test6")
    public class Test6 {
        static int r = 0;
        public static void main(String[] args) {
            test();
        }
        private static void test() {
            log.debug("开始");
            Thread t = new Thread("t1") {
                @Override
                public void run() {
                    log.debug("开始");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    log.debug("结束");
                    r = 10;
                }
            };
            t.start();
            log.debug("r的值是{}", r);
            log.debug("结束");
        }
    }
    登入後複製

    Java執行緒中的start方法和run方法怎麼使用#因為主執行緒和$t1$執行緒是並行的,$t1$執行緒需要$1s$後才能計算出$r$的值,而主執行緒一開始就要列印$r$的值,因此列印的值為0

    ##解決方法:

    在$t.start();$後邊加上$t.join();$即可。 $join$的作用是等待某個執行緒運行結束。 以呼叫方的角度來說,需要等待結果回傳才能繼續執行就是同步,不需要等待回傳結果就能繼續執行的就是非同步。


    因此$join$方法實際上是讓其同步執行Java執行緒中的start方法和run方法怎麼使用

    #有實效的等待

    $join(毫秒)$方法裡可以有一個參數是傳入等待的時間,如果執行緒執行時間大於等待時間,等待時間到了之後,就會停止等待。如果執行緒執行時間小於等待時間,則執行緒執行完畢之後,等待也會跟著結束。不會把設定的等待時間過完。

    interrupt方法

    打断$sleep, wait, join$的线程,即打断阻塞状态的线程
    打断$sleep$的线程,会清空打断状态

    @Slf4j(topic = "c.Test7")
    public class Test7 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("sleep...");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            t.start();
            Thread.sleep(1000);
            log.debug("interrupt");
            t.interrupt();
            log.debug("打断标记: {}", t.isInterrupted());
        }
    }
    登入後複製

    Java執行緒中的start方法和run方法怎麼使用

    打断正常运行的线程,不会清空打断状态

    因此我们可以在线程中判断打断标记,来决定是否被打断,以及执行被打断之前的收尾工作。

    @Slf4j(topic = "c.Test8")
    public class Test8 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread("t1"){
                @Override
                public void run() {
                    while (true) {
                        if (Thread.currentThread().isInterrupted()) {
                            log.debug("线程被打断了");
                            break;
                        }
                    }
                }
            };
            t.start();
            Thread.sleep(1000);
            log.debug("interrupt");
            t.interrupt();
        }
    }
    登入後複製

    守护线程

    默认情况下,$java$需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其他非守护线程运行结束了,即使守护线程的代码没有执行完毕,也会强制结束。

    @Slf4j(topic = "c.Test10")
    public class Test10 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread("t1") {
                @Override
                public void run() {
                    while (true) {
    
                    }
                }
            };
            //设置线程为守护线程
            t.setDaemon(true);
            t.start();
            Thread.sleep(1000);
            log.debug("主线程结束");
        }
    }
    登入後複製

    如果不把$t$设置为守护线程,则因为线程内部的死循环,导致程序不会结束运行。

    以上是Java執行緒中的start方法和run方法怎麼使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳圖形設置
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您聽不到任何人,如何修復音頻
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.聊天命令以及如何使用它們
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    Java 中的完美數 Java 中的完美數 Aug 30, 2024 pm 04:28 PM

    Java 完美數指南。這裡我們討論定義,如何在 Java 中檢查完美數?

    Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

    Java 版 Weka 指南。這裡我們透過範例討論簡介、如何使用 weka java、平台類型和優點。

    Java 中的史密斯數 Java 中的史密斯數 Aug 30, 2024 pm 04:28 PM

    Java 史密斯數指南。這裡我們討論定義,如何在Java中檢查史密斯號?帶有程式碼實現的範例。

    Java Spring 面試題 Java Spring 面試題 Aug 30, 2024 pm 04:29 PM

    在本文中,我們保留了最常被問到的 Java Spring 面試問題及其詳細答案。這樣你就可以順利通過面試。

    突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

    Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

    Java 中的時間戳至今 Java 中的時間戳至今 Aug 30, 2024 pm 04:28 PM

    Java 中的時間戳記到日期指南。這裡我們也結合範例討論了介紹以及如何在java中將時間戳記轉換為日期。

    Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

    膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

    如何在Spring Tool Suite中運行第一個春季啟動應用程序? 如何在Spring Tool Suite中運行第一個春季啟動應用程序? Feb 07, 2025 pm 12:11 PM

    Spring Boot簡化了可靠,可擴展和生產就緒的Java應用的創建,從而徹底改變了Java開發。 它的“慣例慣例”方法(春季生態系統固有的慣例),最小化手動設置

    See all articles