我之见--java多线程 线程安全集合类

    java本身对多线程的支持是很充分的,但在jdk1.5之前集合对多线程的操作几乎都是不安全的,但是集合又是我们经常用到的,如果用不好经常会出问题,下面我们来解析一下:就拿我们最简单的Vector类来说,我们先来看一下使用它的常规用法:   

private static void removeObject(Vector<String> vector,int index) {
        vector.remove(index);
    }
这样的使用在多线程的情况下感觉会出现,index可能会超出vector容量的大小,可能你会说我们可以在使用之前先检测。

因此代码这样改成这样:

    private void removeObject(Vector<String> vector,int index) {
        if(vector.size()<index) {
            return;
        }
        vector.remove(index);
    }
  确实可能是这样避免刚才出现的问题,如果我们还要用另外的一个方法,删除vector最后一个元素,因此我们添加了下面方法:      

  private void removeLast(Vector<String> vector) {
        int index = vector.size() - 1;
        vector.remove(index);
    }
 这样也是似乎也是没有问题了,如果两个线程是顺序执行的话,但实际情况我们可能并不能保证线程的顺序执行。因为我们想到了加锁来保证线程的安全,因此上面的方法就变成了,下面的代码:

   private void removeObject(Vector<String> vector,int index) {
        synchronized (vector) {            
            if(vector.size()<index) {
                return;
            }
            vector.remove(index);
        }
    }
    
    private void removeLast(Vector<String> vector) {
        synchronized (vector) {            
            int index = vector.size() - 1;
            vector.remove(index);
        }
    

此时的代码确实是线程安全的,没有任何问题,如果我们现在想添加向集合里面添加元素,因此代码可以这样写:
   private void addObject(Vector<String> vector, String e) {
            vector.add(e);
    }
当我们很高兴的时候,却出现了另外一个错误;ConcurrentModificationException,因此我们又不得不对上面的代码进行加锁,几乎我们对集合的任何操作都需要加锁,每个操作都加锁资源消耗是非常大的,而且特别是当我们对集合进行遍历操作的时候,如果其他线程因为加锁的原因必须等待,这样是很不好的。
   但是到了jdk 5.0之后java提供了很多并发容器来改进同步容器的性能。比如:ConcurrentHashMap 和CopyOnWriteArrayList; 同时还新增了两种容器的类型:
 Queue和BlockingQueue.  BlockingQueue是一种支持阻塞式添加和获取元素的方式,因此我们可以很简单的实现生产者和消费者模式。
   针对上面的 ConcurrentModificationException异常我们可以CopyOnWriteArrayList集合可以很快搞定,这是一种写时才复制的容器,当我们在写的时候,发现有别的线程在读,我们先创建新的“副本”,从而可以实现可变性,不过如果我们每次在改变的时候都进行复现,这需要很大的开销。因此这种集合只能针对读操作比较对,写操作比较少的情况,似乎于观察者模式。
   ConcurrentHashMap 改变了以往我们在每个操作上面都加锁的情况,采用新的加锁方式,我们可以叫做分段锁,这是一种基于散列的锁,任何读写操作都可以并发访问map,并且一定数量的写入线程可以并发执行。后面文章我们会一起学习。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值