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();    	}    }