代碼系本人逐字逐句編寫所得,轉載請注明出處,謝謝合作!
多線程售票的問題算是老生常談了,筆者是Java初學者,曾為弄清楚這個問題在度娘里搜過好多篇關於這個問題的代碼,發現正確的代碼還是很有限.
粘貼復制的現象很嚴重,而且大多數代碼問題主要是在打印車票超過數量的問題上(部分會打印出負數票號),還有個別會出現表面看似打印結果正確,但其實程序中還有線程在等待執行(在Eclipse的控制台看到明顯的"紅點"一直在亮着).以下是筆者自己寫的關於這個問題的代碼,由於個人水平有限,難免有所疏漏,希望大家莫吝賜教!
源代碼:
1 import java.text.NumberFormat; 2 3 public class SellTickets { 4 public static void main(String[] args) { 5 6 //創建車票對象,並初始化車票總數 7 Ticket ticket=new Ticket(1000); 8 9 //創建售票線程 ,並設置窗口名字,然后啟動線程,這里設置四個窗口 10 new Thread(ticket,"窗口A").start(); 11 new Thread(ticket,"窗口B").start(); 12 new Thread(ticket,"窗口C").start(); 13 new Thread(ticket,"窗口D").start(); 14 15 } 16 } 17 18 /** 19 * 采用實現Runnable接口的方式實現多線程 20 */ 21 class Ticket implements Runnable { 22 23 //總的車票數 24 int total; 25 26 Ticket(int total){ 27 this.total=total; 28 } 29 30 //初始車票號碼 1 31 int num = 1; 32 33 @Override 34 public void run() { 35 while (true) { 36 37 synchronized ("") { 38 try { 39 // 任何線程獲取"線程鎖"以后都要先判斷是否還有余票,防止等待的線程多打印車票 40 if (num > total) return; 41 42 // 獲取當前線程名字 43 String threadName = Thread.currentThread().getName(); 44 45 // 格式化票號 46 String ticketNum = FormatTicketNum(num++); 47 48 // 打印火車票,休眠20毫秒模擬打印車票時間 49 Thread.sleep(20); 50 System.out.println(threadName + " 售出火車票No." + ticketNum); 51 52 // 某線程售完最后一張車票時,放出"車票已售罄"提示 53 if (num > total) { 54 System.out.println("車票已售罄!"); 55 return; 56 } 57 } catch (InterruptedException e) { 58 e.printStackTrace(); 59 } 60 } 61 } 62 } 63 64 /** 65 * 格式化車票號碼 66 */ 67 static String FormatTicketNum(int num) { 68 69 NumberFormat nf = NumberFormat.getIntegerInstance(); 70 nf.setMinimumIntegerDigits(3); 71 return nf.format(num); 72 } 73 }
打印結果:
1 窗口D 售出火車票No.001 2 窗口D 售出火車票No.002 3 窗口D 售出火車票No.003 4 窗口D 售出火車票No.004 5 窗口D 售出火車票No.005 6 窗口D 售出火車票No.006 7 窗口D 售出火車票No.007 8 窗口D 售出火車票No.008 9 窗口D 售出火車票No.009 10 窗口D 售出火車票No.010 11 窗口D 售出火車票No.011 12 窗口D 售出火車票No.012 13 窗口D 售出火車票No.013 14 窗口D 售出火車票No.014 15 窗口D 售出火車票No.015 16 窗口D 售出火車票No.016 17 窗口D 售出火車票No.017 18 窗口D 售出火車票No.018 19 窗口D 售出火車票No.019 20 窗口D 售出火車票No.020 21 窗口D 售出火車票No.021 22 窗口D 售出火車票No.022 23 窗口D 售出火車票No.023 24 窗口D 售出火車票No.024 25 窗口D 售出火車票No.025 26 窗口D 售出火車票No.026 27 窗口D 售出火車票No.027 28 窗口D 售出火車票No.028 29 窗口D 售出火車票No.029 30 窗口D 售出火車票No.030 31 窗口D 售出火車票No.031 32 窗口D 售出火車票No.032 33 窗口D 售出火車票No.033 34 窗口D 售出火車票No.034 35 窗口C 售出火車票No.035 36 窗口C 售出火車票No.036 37 窗口C 售出火車票No.037 38 窗口C 售出火車票No.038 39 窗口C 售出火車票No.039 40 窗口C 售出火車票No.040 41 窗口A 售出火車票No.041 42 窗口A 售出火車票No.042 43 窗口A 售出火車票No.043 44 窗口A 售出火車票No.044 45 窗口A 售出火車票No.045 46 窗口A 售出火車票No.046 47 窗口A 售出火車票No.047 48 窗口B 售出火車票No.048 49 窗口B 售出火車票No.049 50 窗口B 售出火車票No.050 51 窗口B 售出火車票No.051 52 窗口B 售出火車票No.052 53 窗口B 售出火車票No.053 54 ... ... .... 55 窗口D 售出火車票No.974 56 窗口D 售出火車票No.975 57 窗口D 售出火車票No.976 58 窗口C 售出火車票No.977 59 窗口C 售出火車票No.978 60 窗口C 售出火車票No.979 61 窗口C 售出火車票No.980 62 窗口C 售出火車票No.981 63 窗口C 售出火車票No.982 64 窗口C 售出火車票No.983 65 窗口C 售出火車票No.984 66 窗口C 售出火車票No.985 67 窗口A 售出火車票No.986 68 窗口A 售出火車票No.987 69 窗口A 售出火車票No.988 70 窗口A 售出火車票No.989 71 窗口A 售出火車票No.990 72 窗口A 售出火車票No.991 73 窗口B 售出火車票No.992 74 窗口B 售出火車票No.993 75 窗口B 售出火車票No.994 76 窗口B 售出火車票No.995 77 窗口B 售出火車票No.996 78 窗口B 售出火車票No.997 79 窗口B 售出火車票No.998 80 窗口A 售出火車票No.999 81 窗口C 售出火車票No.1,000 82 車票已售罄!