java 多線程之synchronized wait/notify解決買票問題


一.Java線程具有五中基本狀態

新建狀態(New):當線程對象對創建后,即進入了新建狀態,如:Thread t = new MyThread();

就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了准備,隨時等待CPU調度執行,並不是說執行了t.start()此線程立即就會執行;

運行狀態(Running):當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。注:就     緒狀態是進入到運行狀態的唯一入口,也就是說,線程要想進入運行狀態執行,首先必須處於就緒狀態中;

阻塞狀態(Blocked):處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的原因不同,阻塞狀態又可以分為三種:

1.等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;

2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態;

3.其他阻塞 -- 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。

 

 

二. Java多線程的創建及啟動

1.繼承Thread類,重寫該類的run()方法。

兩個線程同時運行,隨機產生4位隨機字符

 1 import java.util.Random;
 2 
 3 public class 多線程 {
 4 
 5     public static Object lock = new Object();
 6 
 7     public static void randomString() {
 8         String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 9         Random random = new Random();
10         StringBuffer sb = new StringBuffer();
11         for (int i = 0; i < 4; i++) {
12             int number = random.nextInt(62);
13             sb.append(str.charAt(number));
14         }
15         System.out.print(sb);
16     }
17 
18     public static void main(String[] args) {
19 
20         new Thread(new myTh1()).start();
21         new Thread(new myTh2()).start();
22 
23     }
24 
25 }
26 
27 class myTh1 extends Thread {
28     @Override
29     public void run() {
30         while (true) {
31 
32             try {
33                 synchronized (多線程.lock) {
34                     多線程.randomString();
35                     System.out.print("------"+Thread.currentThread().getName());
36                     System.out.println();
37                 }
38                 sleep(1000);        
39             } catch (InterruptedException e) {
40                 e.printStackTrace();
41             }
42         }
43     }
44 }
45 
46 class myTh2 extends Thread {
47     @Override
48     public void run() {
49         while (true) {
50             try {
51                 synchronized (多線程.lock) {
52                     多線程.randomString();
53                     System.out.print("------"+Thread.currentThread().getName());
54                     System.out.println();
55                 }
56                 sleep(1000);
57             } catch (InterruptedException e) {
58                 e.printStackTrace();
59             }
60         }
61     }
62 }
View Code

2.實現Runnable接口,並重寫該接口的run()方法,該run()方法同樣是線程執行體,創建Runnable實現類的實例,並以此實例作為Thread類的target來創建Thread對象,該Thread對象才是真正的線程對象

主線程和兩個實現Runnable接口的線程同時運行,線程對象只運行5次。

 1 public class 多線程Runnable {
 2 
 3     public static void main(String[] args) {
 4         System.out.println(Thread.currentThread().getName());
 5         try {
 6             Thread.sleep(3000);
 7         } catch (InterruptedException e) {
 8             e.printStackTrace();
 9         }
10         
11         new Thread(new myTh3()).start();
12         new Thread(new myTh4()).start();
13             
14 
15     }
16 }
17     class myTh3 extends Thread{
18         int i=0;
19         @Override
20         public void run() {
21             while (i<5) {
22                 System.out.println(Thread.currentThread().getName());
23                 try {
24                     sleep(2000);
25                 } catch (InterruptedException e) {    
26                     e.printStackTrace();
27                 }
28                 i++;
29             }
30             
31         }
32 
33     }
34     
35     class myTh4 implements Runnable{
36 
37         int i=0;
38         @Override
39         public void run() {
40             while (i<5) {
41                 System.out.println(Thread.currentThread().getName());
42                 i++;
43             }
44         
45     }
46 }
View Code

3.synchronized, wait, notify結合:

 

解決問題三個人去買票,張某有20元,李某10元。趙某5元。電影票5元一張,售貨員只有3張5元的

 

  1 /*問題:
  2  * 三個人去買票,張某有20元,李某10元。趙某5元。
  3  * 電影票5元一張,售貨員只有3張5元的。
  4  * 
  5  * 思路:
  6  * 張某買了票就會少3張5元的
  7  * 李某買了票就會少1張5元的
  8  * 趙某買了票就會多1張5元的
  9  * 所以有三種情況:
 10  * 一。趙某先買,張李都可以買
 11  * 二。張某先買,此時李某買不了,只能等待趙某買了,再買
 12  * 三。李某先買,此時張某買不了,只能等待趙某買了,再買
 13  * 
 14  * 靜態常量:售貨員總錢數 sum=3
 15  * 
 16  *     1.創建三個線程分別為張某,李某,趙某
 17  *     2.判斷此時sum值,合適就買票,減去相應的錢數,不合適就等待。
 18  */
 19 import java.util.ArrayList;
 20 import java.util.Iterator;
 21 import java.util.List;
 22 
 23 public class 多線程3 {
 24 
 25     public static int sum = 3;//設置零錢總張數為3張
 26     public static Object look = new Object();//建立一個鎖
 27 
 28     public static List<Thread> arrayList = new ArrayList<>();//建立集合 保存這三個購買人的線程
 29 
 30     public static void main(String[] args) throws InterruptedException {
 31         //隨機將趙某李某張某添加到集合中
 32         arrayList.add(new li());
 33         arrayList.add(new zhang());
 34         arrayList.add(new zhao());
 35 
 36         //通過迭代器遍歷集合
 37         Iterator<Thread> iterator = arrayList.iterator();
 38 
 39         while (iterator.hasNext()) {
 40             //獲取線程
 41             Thread t = iterator.next();
 42             //線程啟動
 43             t.start();
 44             //線程睡眠
 45             t.sleep(2000);
 46         }
 47 
 48     }
 49 }
 50 /**
 51  * 張某線程
 52  * @author Administrator
 53  *
 54  */
 55 class zhang extends Thread {
 56     @Override
 57     public void run() {
 58         //因為要判斷等待和喚醒,並且操作sum,所以在此處加鎖
 59         synchronized (多線程3.look) {
 60             while (多線程3.sum < 3) {
 61                 try {
 62                     System.out.println("因為此時零錢不足:"+多線程3.sum+"張");
 63                     System.out.println("所以張某沒買到電影票,等待購買");
 64                     多線程3.look.wait();
 65                 } catch (InterruptedException e) {
 66                     e.printStackTrace();
 67                 }
 68             }  if (多線程3.sum > 2) {
 69                 多線程3.sum = 多線程3.sum - 3;
 70                 多線程3.look.notify();
 71                 System.out.println("張某買到了電影票");
 72                 System.out.println("此時零錢數為:"+多線程3.sum+"張");
 73             }
 74         }
 75     }
 76 }
 77 /**
 78  * 李某線程
 79  * @author Administrator
 80  *
 81  */
 82 class li extends Thread {
 83     @Override
 84     public void run() {
 85         synchronized (多線程3.look) {
 86             while (多線程3.sum < 1) {
 87                 try {
 88                     System.out.println("因為此時零錢不足:"+多線程3.sum+"張");
 89                     System.out.println("所以李某沒買到電影票,等待購買");
 90                     多線程3.look.wait();
 91                 } catch (InterruptedException e) {
 92                     e.printStackTrace();
 93                 }
 94             }  if (多線程3.sum >= 1) {
 95                 多線程3.sum = 多線程3.sum - 1;
 96                 多線程3.look.notify();
 97                 System.out.println("李某買到了電影票");
 98                 System.out.println("此時零錢數為:"+多線程3.sum+"張");
 99             }
100 
101         }
102     }
103 }
104 /**
105  * 趙某線程
106  * @author Administrator
107  *
108  */
109 class zhao extends Thread {
110     @Override
111     public void run() {
112         synchronized (多線程3.look) {
113             if (多線程3.sum >= 0) {
114                 多線程3.sum = 多線程3.sum + 1;
115                 System.out.println("趙某買到了電影票");
116                 System.out.println("此時零錢數為:"+多線程3.sum+"張");
117                 多線程3.look.notify();
118             }
119         }
120     }
121 }

 

全部都是培訓課后習題,最后一個足足搞了半天,希望我寫的沒毛病,求指教。。謝謝大佬。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM