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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Thread详解

發布時間:2023/12/19 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Thread详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

具體可參考:Java并發編程:Thread類的使用,這里對線程狀態的轉換及主要函數做一下補充。

一. 線程狀態轉換圖

  注意:

  • 調用obj.wait()的線程需要先獲取obj的monitor,wait()會釋放obj的monitor并進入等待態。所以wait()/notify()都要與synchronized聯用。詳見:JAVA多線程之wait/notify
  • 1.1 阻塞與等待的區別

    阻塞:當一個線程試圖獲取對象鎖(非java.util.concurrent庫中的鎖,即synchronized),而該鎖被其他線程持有,則該線程進入阻塞狀態。它的特點是使用簡單,由JVM調度器來決定喚醒自己,而不需要由另一個線程來顯式喚醒自己,不響應中斷
    等待:當一個線程等待另一個線程通知調度器一個條件時,該線程進入等待狀態。它的特點是需要等待另一個線程顯式地喚醒自己,實現靈活,語義更豐富,可響應中斷。例如調用:Object.wait()、Thread.join()以及等待Lock或Condition。

      需要強調的是雖然synchronized和JUC里的Lock都實現鎖的功能,但線程進入的狀態是不一樣的。synchronized會讓線程進入阻塞態,而JUC里的Lock是用LockSupport.park()/unpark()來實現阻塞/喚醒的,會讓線程進入等待態。但話又說回來,雖然等鎖時進入的狀態不一樣,但被喚醒后又都進入runnable態,從行為效果來看又是一樣的。

    二. 主要操作?

    2.1 start()

    新啟一個線程執行其run()方法,一個線程只能start一次。主要是通過調用native start0()來實現。

    1 public synchronized void start() { 2      //判斷是否首次啟動 3 if (threadStatus != 0) 4 throw new IllegalThreadStateException(); 5 6 group.add(this); 7 8 boolean started = false; 9 try { 10        //啟動線程 11 start0(); 12 started = true; 13 } finally { 14 try { 15 if (!started) { 16 group.threadStartFailed(this); 17 } 18 } catch (Throwable ignore) { 19 /* do nothing. If start0 threw a Throwable then 20 it will be passed up the call stack */ 21 } 22 } 23 } 24 25 private native void start0();

    2.2 run()

    run()方法是不需要用戶來調用的,當通過start方法啟動一個線程之后,當該線程獲得了CPU執行時間,便進入run方法體去執行具體的任務。注意,繼承Thread類必須重寫run方法,在run方法中定義具體要執行的任務。

    2.3 sleep()

    sleep方法有兩個重載版本:

    1 sleep(long millis) //參數為毫秒 2 3 sleep(long millis,int nanoseconds) //第一參數為毫秒,第二個參數為納秒

    sleep相當于讓線程睡眠,交出CPU,讓CPU去執行其他的任務。

    但是有一點要非常注意,sleep方法不會釋放鎖,也就是說如果當前線程持有對某個對象的鎖,則即使調用sleep方法,其他線程也無法訪問這個對象。

    2.4 yield()

    調用yield方法會讓當前線程交出CPU權限,讓CPU去執行其他的線程。它跟sleep方法類似,同樣不會釋放鎖。但是yield不能控制具體的交出CPU的時間,另外,yield方法只能讓擁有相同優先級的線程有獲取CPU執行時間的機會。

    注意,調用yield方法并不會讓線程進入阻塞狀態,而是讓線程重回就緒狀態,它只需要等待重新獲取CPU執行時間,這一點是和sleep方法不一樣的。

    2.5 join()

    join方法有三個重載版本:

    1 join() 2 join(long millis) //參數為毫秒 3 join(long millis,int nanoseconds) //第一參數為毫秒,第二個參數為納秒

    join()實際是利用了wait(),只不過它不用等待notify()/notifyAll(),且不受其影響。它結束的條件是:1)等待時間到;2)目標線程已經run完(通過isAlive()來判斷)。

    1 public final synchronized void join(long millis) throws InterruptedException { 2 long base = System.currentTimeMillis(); 3 long now = 0; 4 5 if (millis < 0) { 6 throw new IllegalArgumentException("timeout value is negative"); 7 } 8 9 //0則需要一直等到目標線程run完 10 if (millis == 0) { 11 while (isAlive()) { 12 wait(0); 13 } 14 } else { 15 //如果目標線程未run完且阻塞時間未到,那么調用線程會一直等待。 16 while (isAlive()) { 17 long delay = millis - now; 18 if (delay <= 0) { 19 break; 20 } 21 wait(delay); 22 now = System.currentTimeMillis() - base; 23 } 24 } 25 }

    2.6 interrupt()

    此操作會將線程的中斷標志位置位。如果線程sleep()處于timed_waiting狀態,則還會拋出InterruptException;如果線程在運行態則不會受此影響。

    可以通過以下三種方式來判斷中斷:

    1)isInterrupted()

    此方法只會讀取線程的中斷標志位,并不會重置。

    2)interrupted()

    此方法讀取線程的中斷標志位,并會重置。

    3)throw InterruptException

    拋出該異常的同時,會重置中斷標志位。

    2.7 suspend()/resume()

    掛起線程,直到被resume,才會蘇醒。

    但調用suspend()的線程和調用resume()的線程,可能會因為爭鎖的問題而發生死鎖,所以JDK 7開始已經不推薦使用了。

    ?

    轉載于:https://www.cnblogs.com/waterystone/p/4920007.html

    總結

    以上是生活随笔為你收集整理的Thread详解的全部內容,希望文章能夠幫你解決所遇到的問題。

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