學java時和同學碰到的一道題: 轉自https://blog.csdn.net/qq_40857349/article/details/102809100 某公司組織年會,會議入場時有兩個入口,在入場時每位員工都能獲取一張雙色球彩票,假設公司有100個員工,利用多線程模擬年會入場過程, 並分別統計 ...
學java時和同學碰到的一道題:
轉自https://blog.csdn.net/qq_40857349/article/details/102809100
某公司組織年會,會議入場時有兩個入口,在入場時每位員工都能獲取一張雙色球彩票,假設公司有100個員工,利用多線程模擬年會入場過程,
並分別統計每個入口入場的人數,以及每個員工拿到的彩票的號碼。線程運行後列印格式如下:
編號為: 2 的員工 從後門 入場! 拿到的雙色球彩票號碼是: [17, 24, 29, 30, 31, 32, 07]
編號為: 1 的員工 從後門 入場! 拿到的雙色球彩票號碼是: [06, 11, 14, 22, 29, 32, 15]
//.....
從後門入場的員工總共: 13 位員工
從前門入場的員工總共: 87 位員工
同學使用繼承Thread類來寫:
public class ShuangSeQiu extends Thread{
static int count=1;
int []arr=new int [7];
int countHou=0;
int countQian=0;
public ShuangSeQiu(String name) {
super(name);
}
@Override
public synchronized void run() {
// synchronized (this){
while(count<101){
for (int i = 0; i < arr.length; i++) {
arr[i]=new Random().nextInt(99);
}
if (Thread.currentThread().getName()=="後門"){
countHou++;
}else {
countQian++;
}
System.out.println("編號為"+(count++)+"的員工從"
+Thread.currentThread().getName()
+"入場!拿到的雙色球彩票號碼是:"+ Arrays.toString(arr));
}
if (Thread.currentThread().getName()=="後門"){
System.out.println("從後門入場的員工總共:"+countHou+"位員工"); }
else {
System.out.println("從前門入場的員工總共:"+countQian+"位員工");
}
// }
}
}
//測試類
private static void exe2() {
ShuangSeQiu houMen=new ShuangSeQiu("後門");
ShuangSeQiu qianMen=new ShuangSeQiu("前門");
houMen.start();
qianMen.start();
}
我使用實現Runnable介面來寫:
public class Lottery implements Runnable {
List<Integer> list = new ArrayList<>();
Object lock = new Object();
int total=1;int frontCount=0;int backCount=0;
@Override
public void run() {
while(total<100){
synchronized (lock){
for(int i=0;i<6;i++){
list.add(new Random().nextInt(100));
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(Thread.currentThread().getName()=="前門"){
frontCount++;
}else {
backCount++;
}
System.out.println("編號為:"+(total++)+"的員工從"+Thread.currentThread().getName()+"入場!拿到的雙色球彩票號碼是:"+list);
list.clear();
}
}
if(Thread.currentThread().getName()=="前門"){
System.out.println("從前門入場的員工總共:"+frontCount+"位員工");
}else {
System.out.println("從後門入場的員工總共:"+backCount+"位員工");
}
}
}
//測試類
public class Test {
public static void main(String[] args) {
Lottery lot=new Lottery();
Thread Entry1 = new Thread(lot,"前門");
Thread Entry2 = new Thread(lot,"後門");
Entry1.start();
Entry2.start();
}
}
如果在使用Runnbale實現時,synchronized放在while里程式按預期結果運行,但把synchronized放在run上會出現全部走前門或全部走後門的情況
在和同學討論後,初步得出結論:
使用介面實現時,是對同一個Lottery()對象操作的,所以兩個線程是併發進行,因此在run上使用synchronized時,會鎖定先執行的線程,直到他執行完才進入下一個線程,因此會出現全走前門或全走後門。
使用繼承類實現時,是對兩個對象進行操作,所以兩個線程是並行進行的,由於員工數量count是static靜態變數,只有一個,所以不會出現重覆的員工,但是有時會出現101人的情況(題目是100人),是因為當其中一個線程執行完是99後恰好兩個線程同時再次運行,兩個都進行了count++,就變成了101個人。