最近忙着備考大學四年最後的兩科,昨天剛考完大學全部的考試,可是大學專業是機械,可是本身熱衷於IT行業,想往IT行業走,但願畢業後能成功進入到IT行業,只但願畢業能找到一份Java開發工程師的工做,這樣我才能專研和學習到更高深的技術.但願在畢業前能學到一點Java的精髓,讓我能夠成功進入到IT行業,加油~java
線程問題:安全
1 package demosummary.threadsafety; 2
3 public class Ticket implements Runnable{ 4 //定義票數
5 private int ticket = 100; 6 /**
7 * 執行賣票方法 8 */
9 @Override 10 public void run() { 11 //賣票窗口永久開啓
12 while (true) { 13 //判斷票是否賣完
14 if (ticket > 0) { 15 try { 16 //三秒賣一張票
17 Thread.sleep(3000); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 String name = Thread.currentThread().getName(); 22 System.out.println(name+"正在賣:"+ticket--); 23 } 24 } 25 } 26 } 27
28
29
30
31 package demosummary.threadsafety; 32
33 public class TicketTest { 34 public static void main(String[] args) { 35 //建立線程任務對象
36 Ticket ticket = new Ticket(); 37 //建立三個窗口對象
38 Thread t1 = new Thread(ticket, "窗口1"); 39 Thread t2 = new Thread(ticket, "窗口2"); 40 Thread t3 = new Thread(ticket, "窗口3"); 41 //啓用窗口來賣票
42 t1.start(); 43 t2.start(); 44 t3.start(); 45 } 46 /**
47 * 執行結果 48 * 窗口2正在賣:79 49 * 窗口3正在賣:79 50 * 窗口1正在賣:-1 51 * 出現重複賣同一張票和負票,在現實中是不容許出現的 52 */
53 }
注意:執行結果出現兩種問題多線程
1.出現不一樣窗口賣同一張票,把票賣了兩次併發
2.出現賣不存在的票ide
注意:這兩種問題稱爲線程不安全學習
線程安全問題都是由全局變量及靜態變量引發的。若每一個線程中對全局變量、靜態變量只有讀操做,而無寫 操做,通常來講,這個全局變量是線程安全的;如有多個線程同時執行寫操做,通常都須要考慮線程同步, 不然的話就可能影響線程安全this
線程同步spa
當咱們使用多個線程訪問同一資源的時候,且多個線程中對資源有寫的操做,就容易出現線程安全問題。要解決上述多線程併發訪問一個資源的安全性問題:也就是解決重複票與不存在票問題,Java中提供了同步機制 (synchronized)來解決線程
方法:code
1. 同步代碼塊
2. 同步方法
3. 鎖機制
同步代碼塊
同步代碼塊: synchronized 關鍵字能夠用於方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問
格式:
synchronized(同步鎖){
須要同步操做的代碼
}
同步鎖:對象的同步鎖只是一個概念,能夠想象爲在對象上標記了一個鎖
1. 鎖對象 能夠是任意類型。
2. 多個線程對象 要使用同一把鎖
同步鎖是誰?
對於非static方法,同步鎖就是this。
對於static方法,咱們使用當前方法所在類的字節碼對象(類名.class)。
注意:在任什麼時候候,最多容許一個線程擁有同步鎖,誰拿到鎖就進入代碼塊,其餘的線程只能在外等着 (BLOCKED)
1 package demosummary.threadsafety; 2
3 public class Ticket02 implements Runnable { 4 //定義票數
5 private int ticket = 100; 6
7 Object lock = new Object(); 8 /**
9 * 執行賣票方法 10 */
11 @Override 12
13 public void run() { 14 //賣票窗口永久開啓
15 while (true) { 16 synchronized (lock) { 17 //判斷票是否賣完
18 if (ticket > 0) { 19 try { 20 //三秒賣一張票
21 Thread.sleep(3000); 22 } catch (InterruptedException e) { 23 e.printStackTrace(); 24 } 25 String name = Thread.currentThread().getName(); 26 System.out.println(name + "正在賣:" + ticket--); 27 } 28 } 29 } 30 } 31 } 32
33 package demosummary.threadsafety; 34
35 public class TicketTest02 { 36 public static void main(String[] args) { 37 //建立線程任務對象
38 Ticket02 ticket = new Ticket02(); 39 //建立三個窗口對象
40 Thread t1 = new Thread(ticket, "窗口1"); 41 Thread t2 = new Thread(ticket, "窗口2"); 42 Thread t3 = new Thread(ticket, "窗口3"); 43 //啓用窗口來賣票
44 t1.start(); 45 t2.start(); 46 t3.start(); 47 } 48 }
使用了同步代碼塊能夠解決線程安全問題
同步方法
同步方法:使用synchronized修飾的方法,就叫作同步方法,保證A線程執行該方法的時候,其餘線程只能在方法外等着。
格式:
public synchronized void method(){
可能會產生線程安全問題的代碼
}
1 package demosummary.threadsafety; 2
3 public class Ticket03 implements Runnable { 4 private int ticket = 100; 5
6 /**
7 * 執行賣票方法 8 */
9 @Override 10 public void run() { 11 //賣票窗口永久開啓
12 while (true) { 13 sellTicket(); 14 } 15 } 16
17 private synchronized void sellTicket() { 18 //判斷票是否賣完
19 if (ticket > 0) { 20 try { 21 //三秒賣一張票
22 Thread.sleep(3000); 23 } catch (InterruptedException e) { 24 e.printStackTrace(); 25 } 26 //獲取線程名稱
27 String name = Thread.currentThread().getName(); 28 System.out.println(name + "正在賣:" + ticket--); 29 } 30 } 31 } 32
33
34
35 package demosummary.threadsafety; 36
37 public class TicketTest03 { 38 public static void main(String[] args) { 39 //建立線程任務對象
40 Ticket03 ticket = new Ticket03(); 41 //建立三個窗口對象
42 Thread t1 = new Thread(ticket, "窗口1"); 43 Thread t2 = new Thread(ticket, "窗口2"); 44 Thread t3 = new Thread(ticket, "窗口3"); 45 //啓用窗口來賣票
46 t1.start(); 47 t2.start(); 48 t3.start(); 49 } 50 }
Lock鎖
java.util.concurrent.locks.Lock 機制提供了比synchronized代碼塊和synchronized方法更普遍的鎖定操做, 同步代碼塊/同步方法具備的功能Lock都有,除此以外更強大,更體現面向對象
Lock鎖也稱同步鎖,加鎖與釋放鎖方法化了,以下
public void lock() :加同步鎖。
public void unlock() :釋放同步
1 package demosummary.threadsafety; 2
3 import java.util.concurrent.locks.Lock; 4 import java.util.concurrent.locks.ReentrantLock; 5
6 public class Ticket04 implements Runnable { 7 //定義票數
8 private int ticket = 100; 9
10 //建立鎖對象
11 Lock lock = new ReentrantLock(); 12 /**
13 * 執行賣票方法 14 */
15 @Override 16 public void run() { 17 //賣票窗口永久開啓
18 while (true) { 19 //給線程加鎖
20 lock.lock(); 21 //判斷是否郵票可賣
22 if (ticket > 0) { 23 try { 24 Thread.sleep(1000); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 //獲取線程當前名稱
29 String name = Thread.currentThread().getName(); 30 System.out.println(name+"正在賣"+ticket--); 31 } 32 //釋放線程鎖
33 lock.unlock(); 34 } 35 } 36 } 37
38 package demosummary.threadsafety; 39
40 public class TicketTest04 { 41 public static void main(String[] args) { 42 //建立線程任務對象
43 Ticket04 ticket = new Ticket04(); 44 //建立三個窗口對象
45 Thread t1 = new Thread(ticket, "窗口1"); 46 Thread t2 = new Thread(ticket, "窗口2"); 47 Thread t3 = new Thread(ticket, "窗口3"); 48 //啓用窗口來賣票
49 t1.start(); 50 t2.start(); 51 t3.start(); 52 } 53 }