靜態變量也稱為類變量,由static關鍵字修飾,在任何方法、構造函數或代碼塊外部。類變量在程序啟動時被創建,在程序停止時被銷毀。類變量被存儲在靜態存儲器中。類變量通過類名訪問。
常量,由final關鍵字修飾,靜態變量的特性常量都有,除此之外,常量必須聲明時就被賦值且不能再被改變。常量名一般大寫。常量被存儲在常量存儲器內。
實例變量,聲明在任意方法、構造函數或代碼塊外部。在對象“new”時被創建,對象銷毀時被銷毀。實例變量是對象的一部分,同對象一起存儲在堆中。實例變量通過對象訪問。
局部變量,在方法、構造函數或代碼塊中聲明。局部變量在進入方法、構造函數或塊時創建,退出時被銷毀。局部變量存放在各自棧幀的工作內存中。
常量是線程安全的
常量一旦聲明就禁止修改,所以是線程安全的。
靜態變量(類變量)不是線程安全的
單例(非線程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ private static int count; //聲明靜態變量 public void run() { count = 5; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 獲取的count 值為 "+count ); } @Test public void test(){ ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(ts,"線程"+i).start(); } } }
本應輸出的count全部為10,但是根據結果表明靜態變量在單例模式下非線程安全
[線程21] 獲取的count 值為 5 [線程53] 獲取的count 值為 5 [線程270] 獲取的count 值為 10 [線程37] 獲取的count 值為 5 [線程341] 獲取的count 值為 10 [線程306] 獲取的count 值為 10 [線程126] 獲取的count 值為 5 [線程30] 獲取的count 值為 5 [線程125] 獲取的count 值為 5 [線程117] 獲取的count 值為 5 [線程46] 獲取的count 值為 5 [線程118] 獲取的count 值為 5 [線程110] 獲取的count 值為 5 [線程109] 獲取的count 值為 5 [線程94] 獲取的count 值為 5
更改代碼將ts 更換成 new ThreadSafety()
非單例(非線程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ private static int count; //聲明靜態變量 public void run() { count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 獲取的count 值為 "+count ); } @Test public void test(){ // ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(new ThreadSafety(),"線程"+i).start(); } } }
根據結果發現,靜態變量在非單例模式下也非線程安全
[線程62] 獲取的count 值為 10 [線程118] 獲取的count 值為 10 [線程122] 獲取的count 值為 10 [線程123] 獲取的count 值為 5 [線程121] 獲取的count 值為 10 [線程126] 獲取的count 值為 10 [線程133] 獲取的count 值為 10 [線程119] 獲取的count 值為 5 [線程124] 獲取的count 值為 10 [線程120] 獲取的count 值為 10 [線程95] 獲取的count 值為 10
實例變量 單例模式下是非線程安全的,非單例模式下是線程安全的。
單例模式
import org.junit.Test; public class ThreadSafety implements Runnable{ private int count; //聲明實例變量 public void run() { count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 獲取的count 值為 "+count ); } @Test public void test(){ ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(ts,"線程"+i).start(); } } }
[線程14] 獲取的count 值為 10 [線程27] 獲取的count 值為 10 [線程6] 獲取的count 值為 10 [線程11] 獲取的count 值為 10 [線程16] 獲取的count 值為 10 [線程26] 獲取的count 值為 10 [線程21] 獲取的count 值為 10 [線程23] 獲取的count 值為 5 [線程5] 獲取的count 值為 5 [線程4] 獲取的count 值為 10 [線程3] 獲取的count 值為 5 [線程35] 獲取的count 值為 10 [線程42] 獲取的count 值為 10 [線程7] 獲取的count 值為 10 [線程0] 獲取的count 值為 10
非單例模式(線程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ private int count; //聲明實例變量 public void run() { count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 獲取的count 值為 "+count ); } @Test public void test(){ // ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(new ThreadSafety(),"線程"+i).start(); } } }
局部變量(線程安全)
單例(線程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ public void run() { int count; //聲明局部變量 count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 獲取的count 值為 "+count ); } @Test public void test(){ ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(ts,"線程"+i).start(); } } }
非單例(線程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ public void run() { int count; //聲明局部變量 count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 獲取的count 值為 "+count ); } @Test public void test(){ // ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(new ThreadSafety(),"線程"+i).start(); } } }