您好,登錄后才能下訂單哦!
小編給大家分享一下Java線程如何定義,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
定義一個實現 Runnable 接口的類 A, 并實現該接口中的 run 方法, 最后實例化類 A, 作為 Thread 類的構造參數。
// 定義一個實現 Runnable 接口的類 A, 并實現該接口中的 run 方法 public class A implements Runnable { [@Override](https://my.oschina.net/u/1162528) public void run() { System.out.println("開啟一個縣城... "); } } // 實例化類 A A task = new A(); // 作為 Thread 類的構造參數。 Thread t = new Thread(task);
定義一個繼承 Thread 類的類 A, 并重寫類 A 的 run 方法
注意: 其實還是 Runnable 接口中 run 方法,因為 Thread 類實現了 Runnable接口
// 定義一個繼承 Thread 類的類 A, 重寫類 A 的 run 方法 public class A extends Thread { [@Override](https://my.oschina.net/u/1162528) public void run() { System.out.println(); } } Thread t = new Thread();
其他:通過線程池 或者 實現Callable接口的方法。 暫時不多做介紹
Runnbale 接口的實現類必須重寫 run() 方法, 而 Thread類 的實現類有默認實現的run方法
Runnbale 接口的實現類并不是真正的線程類, 他只是執行線程的一個任務類
Thread 類要想以線程的方式執行run方法,只能依靠Thread類
繼承 Thread 類會造成單繼承的局限性
線程的生命周期指的是從線程的創建到啟動直到結束。
java 線程的 6 種狀態
注意: 這里說的是 java 線程的狀態,并非操作系統的線程狀態
Thread 類中通過枚舉定義了線程的狀態
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
New:new Thread() 后線程的狀態就是新建。
Runnable:線程一旦調用 start() 方法,無論是否運行,狀態都為 Runable, Runable 狀態指示表示線程可以運行,不表示線程當下一定在運行,線程是否運行由虛擬機所在操作系統調度決定。
BLOCKED:線程試圖獲取一個內部對象的 Monitor(進入synchronized方法或synchronized塊)但是其他線程已經搶先獲取,那此線程被阻塞,知道其他線程釋放 Monitor 并且線程調度器允許當前線程獲取到 Monitor,此線程就恢復到可運行狀態。
WAITING:當一個線程等待另一個線程通知調度器一個條件時,線程進入等待狀態。
TIMED_WAITING:和等待類似,某些造成等待的方法會允許傳入超時參數,這類方法會造成計時等待,收到其他線程的通知或者超時都會恢復到可運行狀態。
TERMINATED:線程執行完畢正常結束或執行過程中因未捕獲異常意外終止都會是線程進入被終止狀態
操作系統中線程的5中狀態
新建
就緒
運行
阻塞
終止
操作系統會給每個線程分配時間片, 在某一時刻只執行一個時間片的線程。每個java程序啟動后, jvm會自動幫我們創建兩個線程, 一個是main, 一個是GC
線程調度的實現方式
分時調度模型
讓所有線程輪流獲得CPU的控制權,并且為每個線程平均分配CPU時間片段
搶占式調度模型
選擇優先級相對較高的線程執行,如果所有線程的優先級相同,則隨機選擇一個線程執行 Java虛擬機采用此種調度模型。
用戶線程
也稱非守護線程, jvm會在所有非守護線程結束后隨之離開
守護線程
也稱作后臺線程, 當進程中的所有 非后臺線程 結束后, 后臺線程也會隨之結束。
如何設置后臺線程
在線程啟動前調用setDaemon()方法
為什么GC線程是守護線程?
因為當所有的非守護線程結束后, 也就不會產生垃圾, 那么GC線程也就沒有存在的意義
出現線程不安全的條件
必須存在兩個或者兩個以上的線程。
多個線程共享著一個資源,而且操作資源的代碼有多句。
解決辦法
1. 同步代碼塊
使用 synchronized 修飾代碼塊, 如下所示
public void methodA() { synchronized (this){ // doSomething } }
注意的事項:
鎖對象可以是任意的一個對象。
鎖對象必須是多個線程共享 的資源。
調用了sleep方法的線程并不會釋放鎖對象。
如果不存在著線程安全問題,千萬不要使用同步代碼塊或者是同步函數, 因為會降低效率的。
2. 同步函數
使用synchronized修飾該函數則稱作為同步函數, 如下所示。
public synchronized void methodA() { // doSomething }
注意的事項:
非靜態同步函數的鎖對象是this對象,靜態函數的鎖對象是當前所屬類的class文件對象。
同步函數的鎖對象是固定的,無法更改。
推薦使用: 同步代碼塊
同步代碼塊的鎖對象可以由我們自己指定,同步函數的鎖對象是固定的。
同步代碼塊可以隨意指定那個范圍需要被同步,而同步函數必須是整個函數都同步, 代碼不靈活。
死鎖出現的條件
必須存在兩個及兩個以上的線程
這些線程共享兩個及兩個以上的資源
多線程各自持有不同的鎖,并試圖獲取對方已持有的鎖
如何解決
以上是“Java線程如何定義”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。