打字猴:1.700445519e+09
1700445519
1700445520 //启动退票线程
1700445521
1700445522 returnThread.start();
1700445523
1700445524 //启动售票线程
1700445525
1700445526 saleThread.start();
1700445527
1700445528 }
1700445529
1700445530 模拟火车站售票程序,先初始化一堆火车票,然后开始出售,同时也有退票产生,这段程序有没有问题?可能会有读者看出了问题,ArrayList是线程不安全的,两个线程访问同一个ArrayList数组肯定会有问题。
1700445531
1700445532 没错,确定有问题,运行结果如下:
1700445533
1700445534 Exception in thread”Thread-1”java.util.ConcurrentModifcationException
1700445535
1700445536 at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
1700445537
1700445538 at java.util.AbstractList$Itr.next(AbstractList.java:343)
1700445539
1700445540 at Client$2.run(Client.java:28)
1700445541
1700445542 运气好的话,该异常马上就会报出。也许有人会说这是一个典型错误,只须把ArrayList替换成Vector即可解决问题,真的是这样吗?我们把ArrayList替换成Vector后,结果照旧,仍然抛出相同的异常,Vector已经是线程安全的,为什么还报这个错误呢?
1700445543
1700445544 这是因为他混淆了线程安全和同步修改异常,基本上所有的集合类都有一个叫做快速失败(Fail-Fast)的校验机制,当一个集合在被多个线程修改并访问时,就可能会出现ConcurrentModificationException异常,这是为了确保集合方法一致而设置的保护措施,它的实现原理就是我们经常提到的modCount修改计数器:如果在读列表时,modCount发生变化(也就是有其他线程修改)则会抛出ConcurrentModificationException异常。这与线程同步是两码事,线程同步是为了保护集合中的数据不被脏读、脏写而设置的,我们来看线程安全到底用在什么地方,代码如下:
1700445545
1700445546 public static void main(String[]args){
1700445547
1700445548 //火车票列表
1700445549
1700445550 final List<String>tickets=new ArrayList<String>();
1700445551
1700445552 //初始化票据池
1700445553
1700445554 for(int i=0;i<100000;i++){
1700445555
1700445556 tickets.add(“火车票”+i);
1700445557
1700445558 }
1700445559
1700445560 //10个窗口售票
1700445561
1700445562 for(int i=0;i<10;i++){
1700445563
1700445564 new Thread(){
1700445565
1700445566 public void run(){
1700445567
1700445568 while(true){
[ 上一页 ]  [ :1.700445519e+09 ]  [ 下一页 ]