实现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..