现在的位置: 首页 > 综合 > 正文

多线程(七)并发集合

2013年10月07日 ⁄ 综合 ⁄ 共 1639字 ⁄ 字号 评论关闭

在前面的例子中,使用了guarded block和同步方法,在多个线程存取同共享对象FileArray时,防止出现线程间干扰。

(不熟悉guarded block和同步方法的同学,强烈建议先去看这个系列的前面几篇。)

 

实际上有更简便安全的方法,因为java提供了线程安全的并发集合对象(concurrent collections)。使用这些集合,可以自动实现线程安全,从而简化代码。

The java.util.concurrent package includes a number ofadditions to the Java Collections Framework. These are most easilycategorized by the collection interfaces provided:

  • BlockingQueue 定义了一个先进先出的数据结构。可以在试图向一个已满队列中再加入对象,或试图从一个空队列中取出时,实现阻塞或超时。

在前面的例子中,我们使用了wait和notifyall方法来实现 guarded block。而使用BlockingQueue则会自动实现。

注意BlockingQueue只是一个接口,而实现了这个接口的类有:

ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedTransferQueue, PriorityBlockingQueue, SynchronousQueue

BlockingQueue接口定义的不同的方法对于现在无法满足,但将来可能满足的条件有不同的响应:

比如调用add()方法向一个已满queue中添加element时,会抛出异常。调用offer()则会返回false。调用put()则会被阻塞,直到有空间放入element时放入。

java api这部分介绍比较详细,值得一看。

  • ConcurrentMap是java.util.Map的子接口,它提供了有用的原子操作。可以实现在一个map中存在一个key时,删除或覆盖key-value pair,或一个key不存在时添加key-value
    pair.

The standard general-purpose implementation ofConcurrentMap isConcurrentHashMap, which is a concurrent analog ofHashMap.想想在前面的例子中,为了防止scanner会重复向FileArray中存入同一个file,不得不使用重命名的方法:scanner将file放入FileArray时,会同时重命名文件为.upload。而scanner再次扫描目录时,会忽略.upload文件。而使用这个集合是不是就可以避免了呢?

实现了该接口的类是:ConcurrentHashMap, ConcurrentSkipListMap

  • ConcurrentNavigableMap 一个实现了模糊匹配的ConcurrentMap.The standard general-purpose implementation ofConcurrentNavigableMap isConcurrentSkipListMap,
    which is a concurrent analog of TreeMap.

实现了该接口的类是:ConcurrentSkipListMap

接下来,就使用concurrent collections来改写前面的例子。

对于前面的FTP传输文件的例子,可以使用BlockingQueue,但在scanner将file放入queue时,仍然需要重命名来防止重复放入。

而使用ConcurrentMap,可以将文件名中的关键信息作为key,并在该key不存在时才向map中添加,从而防止scanner重复放入文件。

改代码去了~~~

貌似很容易遇到ConcurrentModificationException。。。

抱歉!评论已关闭.