Java 多執行緒練習

  • 2019 年 10 月 4 日
  • 筆記

題目:某公司組織年會,會議入場時有兩個入口,在入場時每位員工都能獲取一張雙色球彩票,假設公司有100個員工,利用多執行緒模擬年會入場過程,
並分別統計每個入口入場的人數,以及每個員工拿到的彩票的號碼。執行緒運行後列印格式如下:
編號為: 2 的員工 從後門 入場! 拿到的雙色球彩票號碼是: [17, 24, 29, 30, 31, 32, 07]
編號為: 1 的員工 從後門 入場! 拿到的雙色球彩票號碼是: [06, 11, 14, 22, 29, 32, 15]
//…..
從後門入場的員工總共: 13 位員工
從前門入場的員工總共: 87 位員工
 
分析:兩個入口對應兩個執行緒,獲取彩票的方法覆寫Runnable介面的run方法實現,我把這個實現了Runnable介面的類稱作Paper類,裡面用id欄位記錄員工編號,並提供get,set方法。設置第3個執行緒來作為隨機控制100個員工進出哪個入口,因為是員工進入了入口,入口才相應彩票方法,所以我用了等待喚醒機制(這裡要注意,這個等待喚醒機制必須要在同步塊中,還要用同一把鎖。)
 
程式碼:

class Paper implements Runnable {        boolean bFlag = false;        private int id;        public void setId(int id) {            this.id = id;      }        public int getId() {          return this.id;      }        public String position;        private List<String> listPosCount = new ArrayList<String>();        private HashMap<Integer, int[]> dic = new HashMap<Integer, int[]>();        private List<Integer> myList = new ArrayList<Integer>();        private int[] getNumbers(int size) {            int numbers[] = new int[size];            for (int i = 0; i < size;) {                boolean flag = false;                numbers[i] = (int) (Math.random() * 100);                for (int j = 0; j < i; j++) {                    if (numbers[j] == numbers[i]) {                        flag = true;                        break;                    }              }                if (flag == true) {                    continue;              }                i++;          }          return numbers;      }        @Override      public void run() {          synchronized (this) {              while (myList.size() < 100) {                    while (!bFlag) {                        try {                            this.wait();                        } catch (InterruptedException e) {                            e.printStackTrace();                      }                  }                    this.bFlag = false;                    if (!myList.contains(id)) {                        myList.add(id);                      if (position == "qian門" || position == "後門")                          listPosCount.add(position);                        int nums[] = getNumbers(7);                        dic.put(id, nums);                        System.out                              .println("編號為: " + id + " 的員工 從" + position + " 入場! 拿到的雙色球彩票號碼是:" + Arrays.toString(nums));                    } else {                      }                  this.notifyAll();              }                int a = 0, b = 0;              for (String str : listPosCount) {                    if (str == "後門")                      a++;                  if (str == "qian門")                      b++;                }              System.out.println("從後門入場的員工總共:" + a + " 位員工");              System.out.println("從後門入場的員工總共:" + b + " 位員工");            }      }  }

//——————————————————————————–
//測試main函數
public class ThreadLearn2 {    	public static void main(String[] args) {    		Paper p = new Paper();    		Thread th1 = new Thread(p);  		Thread th2 = new Thread(p);    		Runnable run1 = new Runnable() {    			@Override  			public void run() {  				synchronized (p) {      					List<Integer> list = new ArrayList<Integer>();    					while (list.size() < 100) {  						int i = (int) (Math.random() * 100);    						if (list.indexOf(i) == -1) {    							p.setId(i);    							list.add(i);    							p.bFlag = true;    							int num = (int) (Math.random() * 100) % 2;    							if (num == 1) {    								p.position = "後門";  							} else {  								p.position = "qian門";    							}  							p.notifyAll();    							while (p.bFlag) {    								try {    									p.wait();    								} catch (InterruptedException e) {    									e.printStackTrace();  								}  							}    						}    					}    				}  			}    		};    		Thread th3 = new Thread(run1);    		th1.start();  		th2.start();  		th3.start();    	}    }