Java并发编程实践读书笔记(三)

CopyOnWriteArrayList 和 CopyOnWriteArraySet

获得iterator以后,队列被改变,不会抛出ConcurrentModificationException,而是原封不动把没有改动的队列元素输出。
@SuppressWarnings("unchecked")
	public static void main(String args[]) {
		String[] ss = { "aa", "bb", "cc" };
		List list1 = new CopyOnWriteArrayList(Arrays.asList(ss));
		List list2 = new ArrayList(Arrays.asList(ss));
		Iterator itor1 = list1.iterator();
		Iterator itor2 = list2.iterator();
		list1.add("New");
		list2.add("New");
		try {
			printAll(itor1);
		} catch (ConcurrentModificationException e) {
			System.err.println("Shouldn't get here");
		}
		try {
			printAll(itor2);
		} catch (ConcurrentModificationException e) {
			System.err
					.println("Will get here.ConcurrentModificationException occurs!");
		}
	}

	@SuppressWarnings("unchecked")
	private static void printAll(Iterator itor) {
		while (itor.hasNext()) {
			System.out.println(itor.next());
		}
	}
-----------OUTPUT-----------
aa
bb
cc
Will get here.ConcurrentModificationException occurs!

ConcurrentMap

    java.util.concurrent.ConcurrentMap  接口和  ConcurrentHashMap  实 现类只能在键不存在 时将元素加入到 map 中,只有在键存在并映射到特定值时才能从 map 中删除一个元素。主要定义了下面几个方法(K 表示键的类型,V 表示值的类型):
  1. V  putIfAbsent(K  key,V  value):如果指定键已经不再与某个值相关联,则将它与给定值关联。 
  2. boolean remove(Object key,Object value):只有目前将键的条目映射到给定值时,才移除该键的条目。 
  3. boolean replace(K key,V oldValue,V newValue):只有目前将键的条目映射到给定值时,才替换该键的条目。 
  4. V replace(K key,V value):只有目前将键的条目映射到某一值时,才替换该键的条目。 
  5. putIfAbsent()  方法用于在  map  中进行添加。这个方法以要添加到 ConcurrentMap 中的键的值为参数,就像普通的  put()  方法,但是只有在 map 不包含这个键时,才能将键加入到  map  中。如果  map  已经包含这个键,那么这个键的现有值就会保留。  putIfAbsent()  方法是原子的。等价于下面的代码(除了原子地执行此操作之外): 
if (!map.containsKey(key))  
      return map.put(key, value); 
  else 
       return map.get(key);
    6.  像  putIfAbsent()  方法一样,重载后的  remove()  方法有两个参数:键和值。在调用时, 只有当键映            射到指定的值时才从  map  中删除这个键。如果不匹配,那么就不删除这个键, 并返回  false。如果值            匹配键的当前映射内容,那么就删除这个键,这个方法是原子性的。
 这种操作的等价源代码(除了原子地执行此操作之外): 
if (map.containsKey(key) && map.get(key).equals(value)) { 
       map.remove(key); 
       return true; 
   } else return false;
总之,ConcurrentMap 中定义的方法是原子性的。 

BlockingQueue

  1. boolean  add(Object  e):将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回  true,如果当前没有可用的空间,则抛出  IllegalStateException。
  2. public boolean offer(Object element):将指定的元素插入此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于  add(E),后者可能无法插素,而只是抛出一个异常。 
  3. public Object remove():获取并移除此队列的头。 
  4. public Object poll();获取并移除此队列的头,如果此队列为空,则返回  null。
  5. public Object element();获取但是不移除此队列的头。此队列为空时将抛出一个异常。
  6. public Object peek();获取但不移除此队列的头;如果此队列为空,则返回  null。
五个队列所提供的各有不同: 
    ArrayBlockingQueue  :一个由数组支持的有界队列。
    LinkedBlockingQueue  :一个由链接节点支持的可选有界队列。
    PriorityBlockingQueue  :一个由优先级堆支持的无界优先
    DelayQueue  :一个由优先级堆支持的、基于时间的调度队列。   
    SynchronousQueue  :一个利用 BlockingQueue  接口的简单聚集(rendezvous)机制。 
    前两个类  ArrayBlockingQueue  和  LinkedBlockingQueue 几乎相同,只是在后备存储器 方 面 有 所 不 同 , LinkedBlockingQueue  并 不 总 是 有 容 量 界 限 。 无 大 小 界 限 的  Link edBlockingQueue 类 在 添 加 元 素 时 永 远 不 会 有 阻 塞 队 列 的 等 待 ( 至 少 在 其 中 有  Integer.MAX_VALUE 元素之前不会)。
    PriorityBlockingQueue  是具有无界限容量的队列,它利用所包含元素的  Comparable  排 序顺序来以逻辑顺序维护元素。可以将它看作  TreeSet  的可能替代物。例如,在队列中加入字符 符串  One、Two、Three  和  Four  会导致  Four  被第一个取出来。对于没有天然顺序的 元素,可以为构造函数提供一个  Comparator  。不过对  PriorityBlockingQueue  有一个技巧。 从  iterator()  返回的  Iterator  实例不需要以优先级顺序返回元素。如果必须以优先级顺序遍 历所 有 元 素 , 那 么 让 它 们 都 通 过   toArray()  方 法 并 自 己 对 它 们 排 序 , 像  Arrays.sort(pq.toArray())  。
     DelayQueue  实现可能是其中最有意思(也是最复杂)的一个。加入到队列中的元素必须实现新的 Delayed 接口(只有一个方法 long  getDelay(java.util.concurrent.TimeUnit unit))。因为队列的大小没有界限,使得添加可以立即返回,但是在延迟时间过去之前,不 能从队列中取出元素。如果多个元素完成了延迟,那么最早失效/失效时间最长的元素将第 一个取出。

你可能感兴趣的:(java,Concurrent)