CPU時間片java
上下文切換,切換的時候須要保持任務的狀態, 以便後續接着任務的狀態執行。比較消耗CPU 資源。安全
死鎖問題多線程
能夠經過jconsole 工具來進行檢測:ide
飢餓和活鎖問題很差檢測工具
如下代碼低優先級的線程仍是有可能大多數狀況下獲取CPU時間片的,只是機率上會變小。性能
public class Target implements Runnable { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + "..."); } } } public class Demo8 { public static void main(String[] args) { Thread t = new Thread(new Target()); Thread t1 = new Thread(new Target()); Thread t2 = new Thread(new Target()); Thread t3 = new Thread(new Target()); t.setPriority(Thread.MAX_PRIORITY); //不一樣平臺優先級值不同,建議使用常量 t2.setPriority(Thread.MIN_PRIORITY); t.start(); t2.start(); } }
如何儘可能避免飢餓問題:線程
寫一個數值生成器:3d
單線程環境下:code
public class Sequence { private int value; public int getNext() { return value++; } public static void main(String[] args) { Sequence sequence = new Sequence(); while (true) { System.out.println(sequence.getNext()); } } }
多線程環境:對象
package thread; public class Sequence { private int value; public int getNext() { return value++; } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
會有數據重複的問題,這就是線程安全性問題
線程是多個執行順序流,value++ 至關於 value = value + 1, 是兩步操做
從java字節碼角度來看線程安全性問題:
可使用 javap -verbose Sequence.class 來看字節碼文件
0: aload_0 1: dup 2: getfield #2 // Field value:I 5: dup_x1 6: iconst_1 7: iadd 8: putfield #2 // Field value:I 11: ireturn
類的實例化對象它是放在堆內存中,堆是線程所共享的區域
程序計數器是線程所獨享的區域
Value 是線程共享的區域
如何解決上面代碼的線程安全性問題:
package thread; public class Sequence { private int value; public synchronized int getNext() { return value++; } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " " + sequence.getNext()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
在 getNext() 方法前加了synchronized關鍵字,讓方法變成同步方法就不會再有重複的數據
Synchronized 至關於一個門加了一把鎖,當一個線程執行的時候,就獲取了這把鎖,而後把門鎖上,其餘線程來的時候就要在外面等待,等執行完畢後把鎖釋放,其餘線程才能進來。就會致使同一時刻只會有一個線程執行該段代碼。
本文主要介紹了線程的性能問題,死鎖問題以及如何使用jconsole 查看線程是否發生死鎖,線程的飢餓與公平,線程安全性問題:從字節碼角度來分析線程安全性問題、如何解決線程安全的問題以及在什麼狀況下會出現線程安全性問題。
歡迎掃碼關注,第一時間收到最新文章推送
個人博客即將同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=14jki2ulsej09