我们平时写程序需要经常用到集合类,比如ArrayList、HashMap等,但是这些集合不能够实现并发运行机制,这样在服务器上运行时就会非常的消耗资源和浪费时间,并且对这些集合进行迭代的过程中不能进行操作,否则会出现错误,例如下面程序:
[Java
public class CollectionModifyExceptionTest { 
    public static void main(String[] args) { 
        Collection users = new ArrayList(); 
        users.add(new User("张三",28));    
        users.add(new User("李四",25));            
        users.add(new User("王五",31));    
        Iterator itrUsers = users.iterator(); 
        while(itrUsers.hasNext()){ 
            System.out.println("正在执行!"); 
            User user = (User)itrUsers.next(); 
            if("李四".equals(user.getName())){ 
                users.remove(user); 
            } else { 
                System.out.println(user);                
            } 
        } 
    } 
}    
       程序在执行过程中会报错, 因为定义了一个ArrayList类型的集合,但是在对集合进行迭代的时候又出现了users.remove(user),即从集合从删除数据,对于普通的集合来说这是不允许的,Java 5以后出现的并发集合类就是专门针对普通集合出现不能并发和不能在迭代过程中修改数据等问题而出现的。
     
 并发集合类主要有:
ConcurrentHashMap;          ConcurrentSkipListMap;             
ConCurrentSkipListSet;           CopyOnWriteArrayList;
CopyOnWriteArraySet;         ConcurrentLinkedQueue;

下面其中的某些集合类进行分别简述:

ConcurrentHashMap支持完全并发的检索和更新所希望的可调整并发的哈希表。此类遵守与 Hashtable
相同的功能规范,并且包括对应于 Hashtable 的每个方法的方法版本。不过,尽管所有操作都是线程安全的,但检索操作不 必锁定,并且不
支持以某种防止所有访问的方式锁定整个表。此类可以通过程序完全与 Hashtable 进行互操作,这取决于其线程安全,而与其同步细节无关。
主要构造方法有:
[java] 
ConcurrentHashMap();  //创建一个带有默认初始容量、加载因子和 concurrencyLevel 的新的空映射。 
ConcurrentHashMap(int initialCapacity);   //创建一个带有指定初始容量、默认加载因子和 concurrencyLevel 的新的空映射。 
ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);  //创建一个带有指定初始容量、加载因子和并发级别的新的空映射。 
ConcurrentHashMap(Map<> t);    //构造一个与给定映射具有相同映射关系的新映射。

ConcurrentLinkedQueue是一个基于链接节点的、无界的、线程安全的队列。此队列按照
FIFO(先进先出)原则对元素进行排序,队列的头部 是队列中时间最长的元素。队列的尾部
是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection
时,ConcurrentLinkedQueue 是一个恰当的选择,此队列不允许 null 元素。
主要构造方法有:
[java] 
ConcurrentLinkedQueue();  //创建一个最初为空的 ConcurrentLinkedQueue。 
ConcurrentLinkedQueue(Collection<> c);// 创建一个最初包含给定 collection 的元素的 ConcurrentLinkedQueue,按照此 collection 迭代器的遍历顺序来添加元素

CopyOnWriteArrayList是ArrayList
的一个线程安全的变形,其中所有可变操作(添加、设置,等等)都是通过对基础数组进行一次新的复制来实现的。这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法更

有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。“快照”风格的迭代器方法在创建迭代器时使用了对数组状态的引用。此数组在迭代器的生存期内绝不会更改,因此不可能发生冲突,并且迭代器保证不会抛出

ConcurrentModificationException。自创建迭代器以后,迭代器就不会反映列表的添加、移除或者更改。不支持迭代器上更改元素的操作(移除、设置和添加)。这些方法将抛出
UnsupportedOperationException。
主要构造方法有:
[java] 
CopyOnWriteArrayList();  // 创建一个空列表。 
CopyOnWriteArrayList(Collection<> c); //按照 Collection 的迭代器返回元素的顺序,创建一个包含指定 Collection 的元素的列表。 
CopyOnWriteArrayList(E[] toCopyIn);   //创建一个新的 CopyOnWriteArrayList,它保持给定数组的副本。

CopyOnWriteArraySet是对其所有操作使用 CopyOnWriteArrayList 的 Set。因此,它共享以下相同的基本属性:
它最适合于 set 大小通常保持很小、只读操作远多于可变操作以及需要在遍历期间防止线程间冲突的应用程序。
它是线程安全的。
因为通常需要复制整个基础数组,所以可变操作(添加、设置、移除,等等)的开销巨大。
迭代器不支持可变移除操作。
使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。
主要构造方法包括:
[java] 
CopyOnWriteArraySet();   //创建一个空 set 
CopyOnWriteArraySet(Collection<> c);   //创建一个包含指定 Collection 中所有元素的 set

讲完并发集合类以后再回到本文刚开始的例子中,如果将Collection users = new
ArrayList();改写成Collection users = new
CopyOnWriteArrayList();再运行程序,程序就会正常进行了,结果如下:
[java]
正在执行! 
{name:'张三',age:28} 
正在执行! 
正在执行! 
{name:'王五',age:31}

JAVA Concurrent包 中的并发集合类的更多相关文章

  1. 利用java concurrent 包实现日志写数据库的并发处理

    一.概述 在很多系统中,往往需要将各种操作写入数据库(比如客户端发起的操作). 最简单的做法是,封装一个公共的写日志的api,各个操作中调用该api完成自己操作日志的入库.但因为入数据库效率比较低,如 ...

  2. Java并发(6):concurrent包中的Copy-On-Write容器

    一. concurrent包介绍 在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,而当针对高质量Java多线程并发程序设计时,为防止死蹦等现象的出现,比如使用java ...

  3. 集合框架的类和接口均在java.util包中。 任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换。

    集合框架的类和接口均在java.util包中. 任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换.

  4. java concurrent包的学习(转)

    java concurrent包的学习(转) http://my.oschina.net/adwangxiao/blog/110188 我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常 ...

  5. java Concurrent包学习笔记(一):ExecutorService

    一.介绍 ExecutorService是java.util.concurrent包中的一个线程池实现接口.其有两个实现类: 1)ThreadPoolExecutor:普通线程池通过配置线程池大小,能 ...

  6. 推荐使用concurrent包中的Atomic类

        这是一个真实案例,曾经惹出硕大风波,故事的起因却很简单,就是需要实现一个简单的计数器,每次取值然后加1,于是就有了下面这段代码:           private int counter = ...

  7. java concurrent包的实现原理

      由于java的CAS同时具有 volatile 读和volatile写的内存语义,因此Java线程之间的通信现在有了下面四种方式:   A线程写volatile变量,随后B线程读这个volatil ...

  8. java.io包中的字节流—— FilterInputStream和FilterOutputStream

    接着上篇文章,本篇继续说java.io包中的字节流.按照前篇文章所说,java.io包中的字节流中的类关系有用到GoF<设计模式>中的装饰者模式,而这正体现在FilterInputStre ...

  9. 1.java.io包中定义了多个流类型来实现输入和输出功能,

    1.java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分 类,按功能分为:(C),如果为读取的内容进行处理后再输出,需要使用下列哪种流?(G)   A.输入流和输出流 B ...

随机推荐

  1. ipcalcIP地址计算

    ipcalc命令是一个简单的ip地址计算器,可以完成简单的IP地址计算任务. 语法 ipcalc(选项) 选项 -b:由给定的IP地址和网络掩码计算出广播地址: -h:显示给定UP地址所对应的主机名: ...

  2. 使用Ant 和 Maven打包发布命令行程序(转载)

    From:https://www.linux178.com/Java/maven-release.html 用Java写了一个命令行的小程序,使用的Intellij IDE是IDEA13原来一直使用A ...

  3. php数组插入数据

    php数组插入数据 一.总结 代码要多敲,看是看不会的 php代码直接在页面不好敲,可以去控制器里面敲 二.目标 在一组数中,要求插入一个数,按其原来顺序插入,维护原来排序方式. 三.代码 (1).思 ...

  4. Maven中央仓库信息速查

    http://maven.outofmemory.cn/

  5. Objective-C基础笔记(8)Foundation常用类NSString

    一.创建字符串的方法 void stringCreate(){ //方法1 NSString *str1 = @"A String!"; //方法2 NSString *str2 ...

  6. golang 写文件

    package main import ( "bufio" "fmt" "io" "os" ) func main() ...

  7. HDU 1548 A strange lift(最短路&&bfs)

    A strange lift Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  8. Android 手机插入电脑后提示“”ADB Interface"安装失败的问题

    安装ADB Interface 1. Android Studio开发时,如果在真机上测试并不是那么的顺利.直接将手机插入电脑,并不能识别.往往提示ADB Interface驱动未安装.如下图所示. ...

  9. Oracle实现数据不存在则插入,数据存在则更新(insert or update)

    思路是写一个函数,先按条件查询数据,假设查询到数据则更新.假设没有查询到数据则插入: create or replace function fn_merge_index(statdate in dat ...

  10. oled屏幕模块

    oled屏幕模块似乎是厂家提供的 也许可以根据屏幕驱动芯片去写 根据现在了解的芯片一般有两个:SH1106和SSD1306 不过这次我们用的是SSD1306芯片驱动的屏幕 下面是从裸屏到模块的pcb: ...