Java多線程,
11.1)多線程概念11.2)建立多線程的2種方法11.3)多線程的生命週期11.4)同步(掌握)為什麼需要同步?
因為安全執行緒問題,舉例—銀行取錢問題,多線程對同一個銀行賬戶進行取錢任務,賬戶會出現負值的資產,不符合現實生活
所以,當多個線程訪問同一資源時,很容易“偶然”出現安全問題
什麼是同步
避免出現安全問題的方法就是同步
2種實現同步的方法
第一種是 synchronized代碼塊
synchronized{ //需要保護的代碼 ... }
第二種是 同步方法(用synchronized關鍵字修飾)
public synchronized void func(){ .... }
ThreadLocal類
ThreadLocal 線程局部變數,支援泛型,通過使用線程局部變數也可以避免多線程訪問同一資源時出現“安全問題”,其方式是通過複製多份同一資源的副本供多線程使用,也就是說每一個線程訪問時,都擁有一個副本變數
ThreadLocal 只提供三個三個public方法:
T get():返回此線程局部變數中當前線程副本中的值 void remove():刪除此線程局部變數中當前線程副本中的值 void set(T value):設定此線程局部變數中當前線程副本中的值
使用如下:
1.class Account{ 2. /** 3. * 定義一個ThreadLocal類型的變數,該變數將是一個線程局部變數 4. * 每個線程都會保留該變數的一個副本 5. */ 6. private ThreadLocal<String> name = new ThreadLocal<>(); 7. //定義一個初始化name成員變數的構造器 8. public Account(String name){ 9. this.name.set(name); 10. //下面代碼用於訪問當前線程的name副本的值 11. System.out.println("-----"+this.name.get()); 12. } 13. //name的getter、setter方法 14. public String getName(){ 15. return this.name.get(); 16. } 17. public void setName(String name){ 18. this.name.set(name); 19. } 20.} 21.class MyThread extends Thread{ 22. //定義一個Account類型的成員變數 23. private Account account ; 24. public MyThread(Account acct,String name){ 25. super(name); 26. this.account = acct; 27. } 28. 29. public void run(){ 30. 31. for(int i = 0;i<10;i++){ 32. //當i==6時,輸出將賬戶名代替為當前線程名 33. if(i==6){ 34. account.setName(getName()); 35. } 36. //輸出同一個賬戶的賬戶名與迴圈變數 37. System.out.println(account.getName()+"賬戶i的值:"+i); 38. } 39. } 40.} 41.public class ThreadLocalTest{ 42. public static void main(String[] args){ 43. //啟動兩個線程,共用同一個Account 44. Account acct = new Account("初始名"); 45. /** 46. * 雖然兩個線程共用同一個賬戶,即只有一個賬戶名 47. * 但由於賬戶名是ThreadLocal類,所以每個線程 48. * 都完全擁有各自的賬戶名副本,因此在i==6之後,將看到 49. * 兩個線程訪問同一賬戶時出現不同的賬戶名 50. */ 51. new MyThread(acct,"線程甲").start(); 52. new MyThread(acct,"線程乙").start(); 53. } 54.}