java實現火車票售賣-高併發
阿新 • • 發佈:2018-12-20
實現1:
* 售賣火車票實現1: * 用ArrayList * * 產生的問題: * 重複銷售 * 超量銷售 * * 原因: * 1.size不是原子的 * 2.remove不是原子的 * 3.判斷+操作 不是原子的
package sell_ticket_test; /** * 售賣火車票實現1: * 用ArrayList * * 產生的問題: * 重複銷售 * 超量銷售 * * 原因: * 1.size不是原子的 * 2.remove不是原子的 * 3.判斷+操作 不是原子的 * * @author x1c * */ import java.util.ArrayList; import java.util.List; public class SellTicket1 { static List<String> tickets = new ArrayList<>(); //ArrayList static { for (int i = 0; i < 10000; i++) { tickets.add("票編號:"+i); } } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(()->{ while (tickets.size()>0) { System.out.println(tickets.remove(0)); } } ).start(); } } }
實現2:
使用Vector,如下部分對Vector的介紹
Vector的方法都是同步的 Synchronized
package sell_ticket_test; /** * 售賣火車票實現2: * 用Vector * * 產生的問題: * 超量銷售 * * 原因: * 判斷+操作 不是原子的 * * @author x1c * */ import java.util.Vector; import java.util.concurrent.TimeUnit; public class SellTicket2 { static Vector<String> tickets = new Vector<String>(); //Vector static { for (int i = 0; i < 10000; i++) { tickets.add("票編號:"+i); } } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(()->{ while (tickets.size()>0) { try { TimeUnit.MICROSECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(tickets.remove(0)); } } ).start(); } } }
實現3:
* 售賣火車票實現3: * 用Vector + 判斷和操作加鎖 * *問題: *效率較低
package sell_ticket_test; /** * 售賣火車票實現3: * 用Vector + 判斷和操作加鎖 * *問題: *效率較低 * * @author x1c * */ import java.util.Vector; import java.util.concurrent.TimeUnit; public class SellTicket3 { static Vector<String> tickets = new Vector<String>(); static { for (int i = 0; i < 10000; i++) { tickets.add("票編號:"+i); } } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(()->{ while (true) { synchronized (tickets) { if (tickets.size()<= 0) { break; } try { TimeUnit.MICROSECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+tickets.remove(0)); } } } ).start(); } } }
實現4:
* 售賣火車票實現4: * 用ConcurrentLinkedQueue 判斷和操作不用加鎖 * *此方法 *效率較高 * *原因:底層沒有用Synchronized加鎖操作 *ConcurrentLinkedQueue底層用CAS 樂觀鎖 CAS是一種系統原語 * *CAS的全稱是Compare And Swap 即比較交換 *執行函式:CAS(V,E,N) *果V值等於E值,則將V的值設為N。 *若V值和E值不同,則說明已經有其他執行緒做了更新,則當前執行緒什麼都不做 *詳細瞭解CAS參考:https://blog.csdn.net/mmoren/article/details/79185862
上程式碼:
package sell_ticket_test;
/**
* 售賣火車票實現4:
* 用ConcurrentLinkedQueue 判斷和操作不用加鎖
*
*此方法
*效率較高
*
*原因:底層沒有用Synchronized加鎖操作
*ConcurrentLinkedQueue底層用CAS 樂觀鎖 CAS是一種系統原語
*
*CAS的全稱是Compare And Swap 即比較交換
*執行函式:CAS(V,E,N)
*果V值等於E值,則將V的值設為N。
*若V值和E值不同,則說明已經有其他執行緒做了更新,則當前執行緒什麼都不做
*詳細瞭解參考:https://blog.csdn.net/mmoren/article/details/79185862
*
* @author x1c
*/
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class SellTicket3 {
static Queue<String> tickets = new ConcurrentLinkedQueue<>(); //ConcurrentLinkedQueue package java.util.concurrent;
static {
for (int i = 0; i < 10000; i++) {
tickets.add("票編號:"+i);
}
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
while (true) {
/**
* poll()
* Retrieves and removes the head of this queue,
* or returns {@code null} if this queue is empty.
*/
String sellTickNo = tickets.poll(); //先操作後判斷
if (sellTickNo == null) {
break;
}else {
System.out.println(Thread.currentThread().getName()+"-->"+sellTickNo);
}
}
}
).start();
}
}
}
很明顯此方法,執行時間明顯縮短!大功告成!Ha..