日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发基础篇(六):线程Thread类的start()方法和run()方法

發布時間:2025/3/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发基础篇(六):线程Thread类的start()方法和run()方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點個贊,看一看,好習慣!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收錄,這是我花了 3 個月總結的一線大廠 Java 面試總結,本人已拿大廠 offer。
另外,原創文章首發在我的個人博客:blog.ouyangsihai.cn,歡迎訪問。

一、初識

java的線程是通過java.lang.Thread類來實現的。VM啟動時會有一個由主方法所定義的線程。可以通過創建Thread的實例來創建新的線程。每個線程都是通過某個特定Thread對象所對應的方法run()來完成其操作的,方法run()稱為線程體。通過調用Thread類的start()方法來啟動一個線程。

在Java當中,線程通常都有五種狀態,創建、就緒、運行、阻塞和死亡。
  第一是創建狀態。在生成線程對象,并沒有調用該對象的start方法,這是線程處于創建狀態。
  第二是就緒狀態。當調用了線程對象的start方法之后,該線程就進入了就緒狀態,但是此時線程調度程序還沒有把該線程設置為當前線程,此時處于就緒狀態。在線程運行之后,從等待或者睡眠中回來之后,也會處于就緒狀態。
  第三是運行狀態。線程調度程序將處于就緒狀態的線程設置為當前線程,此時線程就進入了運行狀態,開始運行run函數當中的代碼。
  第四是阻塞狀態。線程正在運行的時候,被暫停,通常是為了等待某個時間的發生(比如說某項資源就緒)之后再繼續運行。sleep,suspend,wait等方法都可以導致線程阻塞。
  第五是死亡狀態。如果一個線程的run方法執行結束或者調用stop方法后,該線程就會死亡。對于已經死亡的線程,無法再使用start方法令其進入就緒。

二、start()方法

1、為什么需要start方法;它的作用是什么?

start()方法來啟動線程,真正實現了多線程運行。
start方法的作用就是將線程由NEW狀態,變為RUNABLE狀態。當線程創建成功時,線程處于NEW(新建)狀態,如果你不調用start( )方法,那么線程永遠處于NEW狀態。調用start( )后,才會變為RUNABLE狀態,線程才可以運行。

2、調用start()方法后,線程是不是馬上執行?

線程不是馬上執行的;準確來說,調用start( )方法后,線程的狀態是“READY(就緒)”狀態,而不是“RUNNING(運行中)”狀態(關于線程的狀態詳細。線程要等待CPU調度,不同的JVM有不同的調度算法,線程何時被調度是未知的。因此,start()方法的被調用順序不能決定線程的執行順序

注意:
由于在線程的生命周期中,線程的狀態由NEW ----> RUNABLE只會發生一次,因此,一個線程只能調用start()方法一次,多次啟動一個線程是非法的。特別是當線程已經結束執行后,不能再重新啟動。

三、run( )方法

1、run方法又是一個什么樣的方法?run方法與start方法有什么關聯?

run()方法當作普通方法的方式調用
run( )其實是一個普通方法,只不過當線程調用了start( )方法后,一旦線程被CPU調度,處于運行狀態,那么線程才會去調用這個run()方法;

2、run()方法的執行是不是需要線程調用start()方法

上面說了,run()方法是一個普通的對象方法,因此,不需要線程調用start()后才可以調用的。可以線程對象可以隨時隨地調用run方法。

#Example1:

Thread t1 = new Thread(new MyTask(1));Thread t2 = new Thread(new MyTask(2));t1.run();t2.run();

上面的輸出結果是固定的:

count的值:1
count的值:2

再看另一個實例:

Thread t1 = new Thread(new MyTask());Thread t2 = new Thread(new MyTask());t1.start();t2.start();

這個輸出結果不是固定的,因為線程的運行沒法預測。運行結果可能不一樣。

MyTask 類:

//實現Runnable接口 class MyTask implements Runnable{int count;public MyTask(int count) {this.count=count;}@Overridepublic void run() {System.out.println("count的值:"+count);} }

#Example2:

1、用start方法啟動線程

public class Main { public static void main(String[] args) { Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); t1.start(); t2.start(); } } class T1 implements Runnable { public void run() { try { for(int i=0;i<10;i++){ System.out.println(i); Thread.sleep(100); //模擬耗時任務 } } catch (InterruptedException e) { e.printStackTrace(); } } } class T2 implements Runnable { public void run() { try { for(int i=0;i>-10;i--){ System.out.println(i); Thread.sleep(100); //模擬耗時任務 } } catch (InterruptedException e) { e.printStackTrace(); } } }

結果:

說明兩線程是并發執行的。

2、先用run方法啟動線程
將上面的start()改為run()

public class Main { public static void main(String[] args) { Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); t1.run(); t2.run(); } }


說明兩線程實際是順序執行的。

總結:

通過實例1和實例和我們可以知道start方法是用于啟動線程的,可以實現并發,而run方法只是一個普通方法,是不能實現并發的,只是在并發執行的時候會調用。

說到這,不知道小伙伴們有沒有明白這兩個方法的區別,如果還有疑問,可以留言交流。

四、start()方法和run()方法源碼解析(基于JDK1.7.0_40)

public synchronized void start() { // 如果線程不是"就緒狀態",則拋出異常! if (threadStatus != 0) throw new IllegalThreadStateException(); // 將線程添加到ThreadGroup中 group.add(this); boolean started = false; try { // 通過start0()啟動線程,新線程會調用run()方法 start0(); // 設置started標記=true started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } } public void run() { if (target != null) { target.run(); } }

五、真正理解Thread類

Thread類的對象其實也是一個java對象,只不過每一個Thread類的對象對應著一個線程。Thread類的對象就是提供給用戶用于操作線程、獲取線程的信息。真正的底層線程用戶是看不到的了。
因此,**當一個線程結束了,死掉了,對應的Thread的對象仍能調用,除了start( )方法外的所有方法(死亡的線程不能再次啟動),如run( )、getName( )、getPriority()**等等

//簡單起見,使用匿名內部類的方法來創建線程Thread thread = new Thread(){@Overridepublic void run() {System.out.println("Thread對象的run方法被執行了");}};//線程啟動thread.start();//用循環去監聽線程thread是否還活著,只有當線程thread已經結束了,才跳出循環while(thread.isAlive()){}//線程thread結束了,但仍能調用thread對象的大部分方法System.out.println("線程"+thread.getName()+"的狀態:"+thread.getState()+"---優先級:"+thread.getPriority());//調用run方法thread.run();//當線程結束時,start方法不能調用,下面的方法將會拋出異常thread.start();
參考資料
  • http://www.cnblogs.com/jinggod/p/8485143.html
  • https://blog.csdn.net/u010568463/article/details/47911181
  • https://blog.csdn.net/xuxurui007/article/details/7685076

點個贊,看一看,好習慣!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收錄,這是我花了 3 個月總結的一線大廠 Java 面試總結,本人已拿大廠 offer。
另外,原創文章首發在我的個人博客:blog.ouyangsihai.cn,歡迎訪問。

最后,再分享我歷時三個月總結的 Java 面試 + Java 后端技術學習指南,這是本人這幾年及春招的總結,已經拿到了大廠 offer,整理成了一本電子書,拿去不謝,目錄如下:

現在免費分享大家,在下面我的公眾號 程序員的技術圈子 回復 面試 即可獲取。

有收獲?希望老鐵們來個三連擊,給更多的人看到這篇文章

1、老鐵們,關注我的原創微信公眾號「程序員的技術圈子」,專注于 Java、數據結構和算法、微服務、中間件等技術分享,保證你看完有所收獲。

2、給俺點個贊唄,可以讓更多的人看到這篇文章,順便激勵下我繼續寫作,嘻嘻。

3、另外,原創文章首發在我的個人博客:blog.ouyangsihai.cn,歡迎訪問。

點贊是對我最大的鼓勵
↓↓↓↓↓↓

總結

以上是生活随笔為你收集整理的并发基础篇(六):线程Thread类的start()方法和run()方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。