多個操做在同一時間內 只能有一個線程運行,其餘線程要等此線程完成以後才能繼續執行。
要解決資源共享的同步操做問題,能夠使用同步代碼塊和同步方法完成。
1.1 同步代碼塊
代碼塊分四種:
(1) 普通代碼塊:是直接定義在方法之中的。
(2)構造塊:是定義在類中的,優先於構造方法執行,能夠重複調用
(3)靜態塊:是使用static關鍵字聲明,又相遇構造塊執行,只執行一次
(4)同步代碼塊:使用synchronized關鍵字聲明,爲同步代碼塊
格式this
synchronized(同步對象)//當前對象做爲同步對象 使用this表示{ 須要同步的代碼 }
class MyThread implements Runnable {public int ticket = 5 ; //定義票的數量public void run() //覆寫run()方法{for(int i=0;i<100;i++) { synchronized(this) //同步代碼塊 對當前對象進行同步{if(ticket>0) //若是還有票{try{ Thread.sleep(2000) ;//時間延遲}catch (InterruptedException e) { e.printStackTrace() ; } System.out.println("賣票 ticket:"+ ticket--) ; } } } } }public class SyncDemo01 {public static void main(String[] args) { MyThread mt = new MyThread() ;//實例化線程對象Thread t1 = new Thread(mt) ; //定義Thread對象Thread t2 = new Thread(mt) ; //定義Thread對象Thread t3 = new Thread(mt) ; //定義第三個售票員t1.start() ; //啓動線程t2.start() ; //開始賣票t3.start() ; //啓動線程} }
使用同步操做,不會出現負數,可是程序執行效果降低
1.2 同步方法
使用synchronized關鍵字將一個方法聲明成同步方法
格式spa
synchronized 方法返回值 方法名稱(參數列表){}
class MyThread implements Runnable {public int ticket = 5 ; //定義票的數量public void run() //覆寫run()方法{for(int i=0;i<100;i++) { this.sale() ; //調用同步方法} }public synchronized void sale() //聲明同步方法 賣票{if(ticket>0) //若是還有票{try{ Thread.sleep(2000) ; }catch (InterruptedException e) { e.printStackTrace() ; } System.out.println("賣票 ticket:"+ ticket--) ; } } }public class SyncDemo02 {public static void main(String[] args) { MyThread mt = new MyThread() ;//實例化線程對象Thread t1 = new Thread(mt) ; //定義Thread對象Thread t2 = new Thread(mt) ; //定義Thread對象Thread t3 = new Thread(mt) ; //定義第三個售票員t1.start() ; //啓動線程t2.start() ; //開始賣票t3.start() ; //啓動線程} }
A 資源共享的時候須要進行同步操做
B 程序中過多的同步會產生死鎖
死鎖 通常狀況下就是表示 在互相等待 。線程
修改標記位 來 中止線程code
class MyThread implements Runnable {private boolean flag = true ; //定義標記位public void run() //覆寫run()方法{int i = 0 ;while(this.flag) //this表示當前對象{ System.out.println(Thread.currentThread().getName() +"運行,i"+(i++)) ; } }public void stop() //定義stop方法{this.flag = false ; //修改標記位} }public class ThreadStopDemo01 {public static void main(String[] args) { MyThread mt = new MyThread() ; //實例化MyThread對象Thread t = new Thread(mt,"當前線程名稱") ; //聲明Thread線程對象t.start() ; //啓動線程try{ Thread.sleep(30) ; }catch (InterruptedException e) { e.printStackTrace() ; } mt.stop() ; //中止線程 //對象.方法()} }