asp.net+Android+IOS開發 、Net培訓、期待與您交流!
(前言:本篇文章主要依據畢向東老師的課程視頻整理而成,如要詳細學習,請觀看畢老師視頻 百度網盤鏈接地址:http://pan.baidu.com/s/1sjQRHDz)
目錄:一、線程的兩種創建方式 二、線程的五種狀態、線程操作中常用的方法 三、多線程安全 四、使用同步的弊端 五、單例設計模式中的多線程(面試重點)
一、線程的兩種創建方式
1、實現Runnable接口(主流)
代碼示例:
1 public class ThreadTest{ 2 3 public static void main(String[] args) throws InterruptedException{ 4 ThreadImple ti=new ThreadImple(); 5 Thread thread=new Thread(ti); 6 7 thread.start(); 8 } 9 }10 class ThreadImple implements Runnable {11 12 @Override13 public void run() {14 for(int i=0;i<60;i++)15 System.out.i);16 }17 }
2、繼承Thread類
1 public class ThreadTest{ 2 3 public static void main(String[] args) throws InterruptedException{ 4 ThreadExtends ti=new ThreadExtends(); 5 6 ti.start(); 7 } 8 } 9 class ThreadExtends extends Thread {10 11 public void run() {12 for(int i=0;i<60;i++)13 System.out.println("extend thread class..."+i);14 }15 }
3、兩種創建方式的區別
實現方式的運行代碼存放在接口子類的run方法中;實現方式避免了單繼承的局限性,建議使用
繼承方式的運行代碼存放在Thread子類的run方法中
二、線程的五種狀態 線程操作中常用的方法

三、多線程安全
問題:一個線程操作多條語句來共享數據時,一個線程對多條語句只執行了一部分,另一個線程便參與進來執行了,導致共享數據出錯。
如何尋找問題: 1、明確哪些代碼示多線程運行代碼 2、明確共享數據 3、明確多線程運行代碼中哪些語句是操作共享數據的。
解決辦法:同步代碼塊:
Synchronized( 鎖 ){
需要被同步的代碼;
}
同步函數:在函數前加synchronized修飾符。
使用同步要滿足三個前提:1、必須有兩個或兩個以上線程 2、必須是多個線程使用同一個鎖
弊端:每次執行時都要判斷鎖,浪費資源。
普通同步函數的鎖是this ,靜態函數的鎖是其所在文件字節碼對象(.class)
簡單模擬售票代碼:
1 /* 2 程序一共創建三個線程模擬三個售票窗口 ticket=100將票號設為1-100 我們希望票號不重復 3 遺憾的是結果會出現票號為負數、相同票號的問題 也就是我們要講到的線程不安全問題 4 */ 5 public class SaleTicketUnsafe { 6 7 public static void main(String[] args) { 8 9 Ticket ticket=new Ticket();10 11 new Thread(ticket).start();12 new Thread(ticket).start();13 new Thread(ticket).start();14 15 }16 17 }18 class Ticket implements Runnable{19 20 private int ticket=100;21 public void run(){22 while(true){23 if(ticket>0){24 try {25 Thread.sleep(10);//線程出錯概率不是很大,所以要讓線程休眠sleep()來將問題暴露出來26 } catch (InterruptedException e) {27 // TODO Auto-generated catch block28 e.printStackTrace();29 }30 System.out.println(Thread.currentThread().getName()+"售票口出售---車票號:"+ticket--);31 }32 }33 34 }35 }
使用同步代碼塊的方式改進后的程序
1 /*同步代碼塊的方式解決了問題*/ 2 public class SaleTicketSafe { 3 4 public static void main(String[] args) { 5 Tickets ticket=new Tickets(); 6 7 new Thread(ticket).start(); 8 new Thread(ticket).start(); 9 new Thread(ticket).start();10 }11 12 }13 class Tickets implements Runnable{14 15 private int ticket=100;16 Object obj=new Object();17 @Override18 public void run() {19 while(true){20 synchronized(obj){//同步代碼塊21 if(ticket>0){22 try {23 Thread.sleep(10);24 } catch (InterruptedException e) {25 // TODO Auto-generated catch block26 e.printStackTrace();27 }28 System.out.println(Thread.currentThread().getName()+"售票口出售---車票號:"+ticket--);29 } 30 }31 }32 }33 34 }
四、使用同步會出現死鎖情況(面試時會要求寫一個死鎖程序)
問題:多線程各自持有不同的鎖沒釋放,而又彼此需要對方的鎖。
原因:同步中嵌套同步,而它們的鎖卻不同
一個簡單的死鎖程序:
1 public class DieLock { 2 3 public static void main(String[] args){ 4 //開啟兩個線程測試 5 Thread t1=new Thread(new Test(true)); 6 t1.start(); 7 Thread t2=new Thread(new Test(false)); 8 t2.start(); 9 }10 }11 class Test implements Runnable{12 boolean flag;13 public Test(boolean f){14 this.flag=f;15 }16 @Override17 public void run() {18 if(flag){19 while(true){20 synchronized(Lock.lockb){21 System.out.println("if locka");22 synchronized(Lock.locka){23 System.out.println("if lockb"); 24 }25 }26 }27 }else{28 while(true){29 synchronized(Lock.locka){30 System.out.println("else locka");31 synchronized(Lock.lockb){32 System.out.println("else lockb"); 33 }34 }35 }36 } 37 }38 //單獨定義兩個不同的鎖39 static class Lock{40 static Object locka=new Object();41 static Object lockb=new Object();42 } 43 }
五、單例設計模式中的多線程(面試重點)
餓漢式、懶漢式(是線程不安全的,需要同步)
將懶漢式同步有兩種方式:
1、下面代碼中在getInstance方法前用synchronized修飾,通過同步函數來解決,每次都要同步比較消耗資源
2、就是注釋中用同步塊的方式,用雙重判斷(s==null)只需同步一次,避免多消耗資源,推薦使用
1 public class Single{ 2 public static void main(String[] args){ 3 4 Singlel s=Singlel.getInstance(); 5 6 } 7 } 8 //懶漢式 9 class Singlel extends Single{10 11 private Singlel(){}12 private static Singlel s=null;13 14 public static synchronized Singlel getInstance(){15 if(s==null)16 s=new Singlel();17 // if(s==null){18 // synchronized(Singlel.class){ 方法二、雙重判斷 ,提高效率19 // if(s==null)20 // s=new Singlel();21 // }22 // }23 return s;24 }25 }26 //餓漢式27 class Singlee extends Single{28 private Singlee(){}29 private static Singlee s=new Singlee();30 31 public static Singlee getInstance(){32 return s;33 }34 35 }
初學者難免錯誤,歡迎評判指教,持續更正ing...........
ASP.Net+Android+IOS開發 、Net培訓、期待與您交流!
新聞熱點
疑難解答