Java并发编程实战 - 第5章 基础构建模块

Java类库提供了丰富的并发基础构建模块

  • 同步容器类
  • 并发容器
  • 阻塞队列
  • 同步器

同步容器类
Vector, Hashtable, Collections.synchronizedXxx
1. 客户端复合操作需要加锁
2. 迭代器与ConcurrentModificationException
迭代时需要对容器加锁,或者“克隆”容器在本地变量的副本上迭代。
3. 隐形迭代器(toString, hashCode, equals, containsAll, removeAll, retainAll, 已经把容器作为参数的构造函数)

并发容器
并发容器改进了同步容器的性能。
并发容器还提供了一些原子的复合操作

ConcurrentHashMap
使用粒度更细的分段锁提高并发性和伸缩性。
返回的迭代器具有弱一致性,不是及时失败,不抛出ConcurrentModificationException异常。
额外的原子操作。

public interface ConcurrentMap<K, V> extends Map<K, V> {
    V putIfAbsent(K key, V value);
    boolean remove(Object key, Object value);
    boolean replace(K key, V oldValue, V newValue);
    V replace(K key, V value);
}

CopyOnWriteArrayList (写入是复制)
在每次修改是,都会创建并发布一个新的容器的副本,从而实现可变性。
迭代器不会抛出ConcurrentModificationException异常。
每当修改容器时都会复制底层的数组,需要开销。仅当迭代操作远远多于修改操作时才使用。

阻塞队列
BlockingQueue 提供了可阻塞的put 和take方法,支持定时的offer和poll方法,可以是有界的和无界的。
ArrayBlockingQueue ->ArrayList
LinkedBlockingQueue ->LinkedList
PriorityBlockinQueue
SynchronizedQueue

适用于生产者和消费者模式
阻塞队列传递了对象的所有权。

Deque 和 BlockingDeque

BlockingQueue的阻塞方法如take()和put()方法,会抛出InterruptedException,和 Thread.sleep方法一样。
线程可以被阻塞,处于阻塞状态(BLOCKED, WAITING, TIMED_WAITING)

中断是线程间的一种协作机制,一个线程可以要求另外一个线程取消操作。
当代码中调用一个将抛出InterruptedException异常的方法时,你自己的方法就是一个阻塞方法,必须处理中断响应。有两个方式:
1. 传递InterruptedException
2. 恢复中断状态以中断当前线程

同步器
CountdownLatch闭锁
一个或者多个线程, 等待另外N个线程完成某个事情之后才能执行。如 所有人都完成跑步比赛,才宣布比赛结束。

Semaphore 信号量
限制访问同一资源的操作数量,可以实现资源池如数据库连接池,或有界阻塞容器。初始值为1的信号量,可以实现互斥锁。

CyclicBarrier栅栏
所有的线程都相互等待,直达它们都到一个栅栏点。如 所有人都到齐了才开始跑步比赛。

Exchanger

构建高效且可伸缩的结果缓存
1. 线程安全委托给底层的并发集合变量
2. 使用FutureTask处理开销很大的计算

public class Memoizer3 <A, V> implements Computable<A, V> {
    private final Map<A, Future<V>> cache
            = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizer3(Computable<A, V> c) {
        this.c = c;
    }

    public V compute(final A arg) throws InterruptedException {
        Future<V> f = cache.get(arg);
        if (f == null) {
            Callable<V> eval = new Callable<V>() {
                public V call() throws InterruptedException {
                    return c.compute(arg);
                }
            };
            FutureTask<V> ft = new FutureTask<V>(eval);
            f = ft;
            cache.put(arg, ft);
            ft.run(); // call to c.compute happens here
        }
        try {
            return f.get();
        } catch (ExecutionException e) {
            throw LaunderThrowable.launderThrowable(e.getCause());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值