博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Java并发编程实战] 第5章 基础构建模块
阅读量:2342 次
发布时间:2019-05-10

本文共 2189 字,大约阅读时间需要 7 分钟。

同步容器类

  • 包括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
queue; public TaskRunner(BlockingQueue
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:两方栅栏,各方在栅栏位置交换数据

转载地址:http://elkvb.baihongyu.com/

你可能感兴趣的文章
memcpy函数和memmove函数实现的区别
查看>>
c++中的公有继承,私有继承和保护继承
查看>>
快排过程分析
查看>>
合并有序数组的时间复杂度
查看>>
归并排序的实现过程
查看>>
堆排序实现代码
查看>>
归并排序和快排的空间复杂度对比
查看>>
select和epoll原理和优缺点使用场景
查看>>
五种IO模型
查看>>
scanf循环接收不确定数量的数据,并存入整型数组中
查看>>
c++中属性,继承和友元
查看>>
extern和#ifndef解决多个文件使用一个全局变量的问题
查看>>
c++构造函数,虚函数相关问题
查看>>
c++中的隐式转换
查看>>
memset引起内存泄露或者找不到虚函数的位置
查看>>
拷贝构造函数与浅拷贝深拷贝的问题
查看>>
c++中string类的实现
查看>>
构造函数里面赋值和初始化列表的方式
查看>>
c++中delete和析构函数之间的区别
查看>>
delete和free之间的区别(new,malloc)
查看>>