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

同步容器类
  • 包括Vector和Hashtable,线程安全的实现方法是:将状态封装起来并对每个公有方法进行同步,使得每次只有一个线程能访问容器的状态

  • 同步容器类都是线程安全的,但在某些情况下需要额外的客户端加锁保护复合操作(迭代、跳转、条件运算)

  • 同步容器的迭代器没有考虑并发修改问题,当它们发现迭代过程中容器被修改了(迭代期间检查与容器关联的计数器是否被修改),会“及时失败”,抛出一个ConcurrentModificationException

  • 单线程代码也可能抛出ConcurrentModificationException,当对象直接从容器中删除而不是通过Iterator.remove来删除时就会抛出这个异常

  • 标准容器的toString/hashCode/equals方法会间接执行迭代操作,同理还有containsAll/removeAll/retainAll等方法,以及把容器作为参数的构造函数

并发容器
  • ConcurrentHashMap:使用了一个包含16个锁的数组,每个锁保护所有散列桶的1/16,提高伸缩性和并发性;已经实现了一些常见的复合原子操作如putIfAbsent…

  • CopyOnWriteArrayList、CopyOnWriteArraySet:代替同步List/Set,迭代期间不需要对容器进行加锁或复制,保留一个对底层基础数组(事实不可变对象)的引用,每次修改都会创建并重新发布一个新的容器副本

阻塞队列和生产者-消费者模式
  • BlockingQueue:简化生产者-消费者设计的实现过程,支持任意数量的生产者和消费者;

  • BlockingQueue有多种实现:

    • LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列,比同步List有更好的并发性

    • PriorityBlockingQueue优先排序队列

    • SynchronousQueue没有存储空间,生产者直接交付工作给消费者,仅当有足够多的消费者,且总有一个消费者准备好获取交付工作时,才适合使用

  • 串行线程封闭:线程间转移对象所有权,之前的所有者不会再访问它

  • Deque、BlockingDeque:对Queue和BlockingQueue进行扩展;工作密取:一个工作者要访问另一个工作者的队列,会从尾部获取,降低队列上的竞争程度

阻塞方法与中断方法
  • 当方法抛出InterruptedException时,表示该方法是一个阻塞方法,如果它被中断,将努力提前结束中断状态

  • 处理对中断的响应:

    • 传递InterruptedException
    • 恢复中断:
      • 当代码是Runnable的一部分时,不能抛出InterruptedException(因为程序是实现了Runnable接口,然后在重写Runnable接口的run方法的时候,那么子类抛出的异常要小于等于父类的异常。而在Runnable中run方法是没有抛异常的)
      • 必须捕获异常,通过调用当前线程上的interrupt方法中断状态,让调用栈中更高层的代码看到引发了一个中断(因为在捕获InterruptedException异常的时候自动将中断标志位置为了false,至少在捕获了InterruptedException异常之后,如果你什么也不想做,那么就将标志重新置为true)
public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;
 
    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }
 
    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }
}
同步工具类
  • 闭锁:延迟线程的进度直到其到达终止状态,用于等待事件发生,一次性对象,一旦进入终止状态就不能被重置,CountDownLatch,await()

  • FutureTask:抽象的可生成结果的计算,也可以做闭锁;有三种状态:等待、正在运行、完成(结果可能是正常结束、取消或异常结束)

  • 计数信号量Semaphore:控制同时访问某个特定资源的操作数量;二值信号量可以用来做互斥体(mutex)

  • 栅栏:所有线程必须同时到达栅栏位置,用于等待其它线程,可以反复在栅栏位置汇集

    • CyclicBarrier:barrier.await()
    • Exchanger:两方栅栏,各方在栅栏位置交换数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值