并发编程补充

concurrenthashmap第一步,初始化segment数组

 

 hashentry的数组

 

 定位segment元素的位置 用段偏移量 和段掩码   concurrentcysize默认值16

先拿到hash值,再散列算法,减少散列冲突  让元素均匀分布在segment上面 从而提高容器的存储效率   不进行再散列的话所有元素都会放到一个segment中

 

 

 

定义成volatile   多线程同时读,保证不会读到过期的值 单线程的写    happens before规则 写在读之前 所以volatile每次都能拿到最新的值

定位到segment用的是高四位 定位元素用的是全部的值  为了避免两次散列的值一样(元素在segment散列开,但没有在hashentry散列开)

 

 

 put  扩容成原数组的两倍,再将原数组散列插入到新数组中

 

 

 

 size统计元素个数  先尝试两次不加锁的方案  ,如果两次线程数有变化,说明有其他线程修改  加锁获取size   

 

 

 

 

 concurrentHashMap1.8     红黑树:优化底层链表的遍历效率   怎样在很短的时间内把大量数据插入到concurrenthashmap

 

 

 

 

 

 

 

 增加一个元素,加载队列的尾部,获取一个元素的时候会返回队列头部的元素

 

 

 

 

e 数据域 next next指针,指向下一个节点

构造函数初始化

 

 node的cas操作避免线程安全问题

 

 

将节点加到队列尾部

1.将入队节点设置为当前节点的下一个节点   2.更新tail节点(如果tail节点的next节点不为空,就将入队节点置为tail节点

 

 

 多线程入队列 offer  ----如果-----且更新tail成功    p=next还没有越过两个节点的情况,会不断更新

 

 失败了表示有其他线程成功更新了tail节点

 

 总共做了两件事情   定位出尾结点 p   用CAS算法  把入队节点设置成尾结点的next节点,如果不成功,就不断重试 p=succ(p)

 

 

hops变量减少tail节点的更新频率,提高入队效率         tail节点与尾结点距离越长,则cas使用越少   每次循环很长时间才能定位到尾结点

 

 

 增加tail变量的读操作 减少写操作,因为volatile写操作的开销远远大于读操作

 

 

出队列:从队列中返回一个节点元素并且清空节点对元素的引用

 

 当head节点有元素,直接弹出head中的元素,而不会去更新head节点

 

 

 

 

阻塞队列  condition实现

 

 队列满的时候,生产者线程put元素,队列会一直阻塞生产者的线程  ,直到队列可用或响应中断退出了

队列空的时候,消费者线程从队列take元素,队列会阻塞消费者线程,直到队列不为空

 

 

超时退出  阻塞队列满的时候,生产者线程往队列插入元素,队列会阻塞生产者一段时间,过了这段时间,生产者线程会退出

无界阻塞队列 用 put offer方法  永远不会被阻塞

 

 

 

 

公平:阻塞的线程可以按照阻塞的先后顺序访问队列

 

 

delayqueue     proirity  延迟期满的时候才能从队列获取元素

保存缓存元素的有效期   使用一个线程循环查询delayqueue,一旦能从delayqueue获取元素说明缓存期到了

 

syncronazedqueue   默认情况下非公平,支持公平访问队列   不存储元素的阻塞队列  每一个put操作必须要等一个take操作,否则就不能添加元素

直接把生产者线程的数据传给消费者线程 不存储元素,吞吐量比其他阻塞队列大

 

 

 

 

linkedtransferqueue    比其他阻塞队列多了transfer方法

 

------------恢复内容开始------------

concurrenthashmap第一步,初始化segment数组

 

 hashentry的数组

 

 定位segment元素的位置 用段偏移量 和段掩码   concurrentcysize默认值16

先拿到hash值,再散列算法,减少散列冲突  让元素均匀分布在segment上面 从而提高容器的存储效率   不进行再散列的话所有元素都会放到一个segment中

 

 

 

定义成volatile   多线程同时读,保证不会读到过期的值 单线程的写    happens before规则 写在读之前 所以volatile每次都能拿到最新的值

定位到segment用的是高四位 定位元素用的是全部的值  为了避免两次散列的值一样(元素在segment散列开,但没有在hashentry散列开)

 

 

 put  扩容成原数组的两倍,再将原数组散列插入到新数组中

 

 

 

 size统计元素个数  先尝试两次不加锁的方案  ,如果两次线程数有变化,说明有其他线程修改  加锁获取size   

 

 

 

 

 concurrentHashMap1.8     红黑树:优化底层链表的遍历效率   怎样在很短的时间内把大量数据插入到concurrenthashmap

 

 

 

 

 

 

 

 增加一个元素,加载队列的尾部,获取一个元素的时候会返回队列头部的元素

 

 

 

 

e 数据域 next next指针,指向下一个节点

构造函数初始化

 

 node的cas操作避免线程安全问题

 

 

将节点加到队列尾部

1.将入队节点设置为当前节点的下一个节点   2.更新tail节点(如果tail节点的next节点不为空,就将入队节点置为tail节点

 

 

 多线程入队列 offer  ----如果-----且更新tail成功    p=next还没有越过两个节点的情况,会不断更新

 

 失败了表示有其他线程成功更新了tail节点

 

 总共做了两件事情   定位出尾结点 p   用CAS算法  把入队节点设置成尾结点的next节点,如果不成功,就不断重试 p=succ(p)

 

 

hops变量减少tail节点的更新频率,提高入队效率         tail节点与尾结点距离越长,则cas使用越少   每次循环很长时间才能定位到尾结点

 

 

 增加tail变量的读操作 减少写操作,因为volatile写操作的开销远远大于读操作

 

 

出队列:从队列中返回一个节点元素并且清空节点对元素的引用

 

 当head节点有元素,直接弹出head中的元素,而不会去更新head节点

 

 

 

 

阻塞队列  condition实现

 

 队列满的时候,生产者线程put元素,队列会一直阻塞生产者的线程  ,直到队列可用或响应中断退出了

队列空的时候,消费者线程从队列take元素,队列会阻塞消费者线程,直到队列不为空

 

 

超时退出  阻塞队列满的时候,生产者线程往队列插入元素,队列会阻塞生产者一段时间,过了这段时间,生产者线程会退出

无界阻塞队列 用 put offer方法  永远不会被阻塞

 

 

 

 

公平:阻塞的线程可以按照阻塞的先后顺序访问队列

 

 

delayqueue     proirity  延迟期满的时候才能从队列获取元素

保存缓存元素的有效期   使用一个线程循环查询delayqueue,一旦能从delayqueue获取元素说明缓存期到了

 

syncronazedqueue   默认情况下非公平,支持公平访问队列   不存储元素的阻塞队列  每一个put操作必须要等一个take操作,否则就不能添加元素

直接把生产者线程的数据传给消费者线程 不存储元素,吞吐量比其他阻塞队列大

 

 

 

 

 linkedtransferqueue   链表组成的无界阻塞队列  比其他阻塞队列多了transfer方法  有消费者正在等待元素,比如说消费者使用take方法或者是带时间限制的poll方法的时候,transfer会将生产者的元素立刻传递给消费者

如果消费者没有等待元素,transfer方法会将元素储存到tail节点上,等这个元素被消费者消费了才会返回

 

 

 

 

 

 

 linkedBlockingqueue   链表组成的双向阻塞  队列    从队列的两端插入或移除元素        多了几个操作队列的入口 多线程同时入队列的时候能减少一半的竞争        用的时候初始化的时候最好设置一下容量

 

 

 

 

为什么阻塞队列能知道队列是否已满   通知模式    队列已满,生产者队列被阻塞,消费者消费了一个线程,就会通知生产者

用了condition方法

 

 

 

 put方法,当队列已满,调用await方法

 

 

 

 

 

 

 

 

fork、join框架

 

 

 

 

 

 如果没有任务,会从其他线程的尾部随机拿任务

 

 

 

posted @ 2021-08-25 02:55  悬崖听风098  阅读(69)  评论(0编辑  收藏  举报