1. 程式人生 > >java實現火車票售賣-高併發

java實現火車票售賣-高併發

實現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..