并发编程 - 跳表、写时复制容器、阻塞队列

什么是跳表

跳表是用于解决链表的查找问题,由于性能上链表比数组新增元素要快,查询比数组要慢,所以因此引入了跳表技术。跳表的实现上,是通过概率性在table上面添加索引,通过索引的方式查询上,解决了速度慢的问题,由于使用了索引,该跳表在数据上是属于有序的列表。

ConcurrentSkipListMap、ConcurrentSkipListSet是有序的列表,它是(CAS)保证了在多线程环境下线程安全的问题,ConcurrentSkipListSet内部使用的就是ConcurrentSkipListMap,在此基础上进行了包装而已。


TreeMap 、TreeSet是有序的列表,它只适合单线程环境下使用,不能保证线程安全的问题,TreeSet内部使用的就是TreeMap,同样也是在此基础上进行包装。


写时复制容器

写时复制容器一般用于读多,写少的情况,实现上是通过对原数组进行copy一份,然后再新数组里面进行操作,如果此时有读操作,实际上还是读取的原数组,只有当新数组处理完毕之后,才会把新数组替换掉原数组。注意此时的可见性并不是弱一致,因为读写操作的不是同一个table,所以没有一致性。

CopyOnWriteArrayList 和 CopyOnWriteArraySet 两个写时复制容器,其中CopyOnWriteArraySet内部采用CopyOnWriteArrayList的实现,除了equals方法之外,其他的大部分都是调用了CopyOnWriteArrayList内部的方法。

阻塞队列
BlockingQueue:队列为空的时候,取时阻塞;队列满了的时候,写时阻塞。实现阻塞,在blockingQueue中关键的方法为put、take。
其实现有:

  • ArrayBlockingQueue:一个由数组组成的有界阻塞队列,使用同一把锁
  • LinkedBlockingQueue:一个由链表组成的有界阻塞队列,读写分离锁+Condition
  • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列,内部采用ReentrantLock以及condition实现锁,同时使用的也是PriorityQueue;
  • DelayQueue:一个使用优先级队列实现的无界阻塞队列,适用于对时间相关的操作,当业务数据到期后,会从此中进行take到并置为无效,内部采用的可重入锁ReentrantLock,以及PriorityQueue;
  • SynchronousQueue:一个不存储元素的阻塞队列,即每次put后需要take才能继续put,采用的可重入锁(ReentrantLock),有公平和非公平两种形式;
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列,添加元素的时候,会尝试去判断当前是否有take的线程,如果有,那么直接交出去,而不进行入队,使用的locksupport;
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列,即可以从头/尾进行插入/取出,使用的可重入锁(ReentrantLock)以及condition通知其不为空不满,使用了工作密取;
  • 个人理解:BlockingQueue是基于AQS实现的阻塞队列,BlockingQueue内部存在一个queue数组,用于存放提交的数据,在多线程调度下进行数据传递。从而实现根据数据queue数组进行线程的阻塞。

例子:使用blockingQueue实现一个阻塞队列
使用到了以下几个类:testQueue(测试类)、readQueue(读取元素类)、writeQueue(写入元素类)、smallQueue(实现blockingQueue类)、Order(业务类)

  • testQueue类代码:
package queue;
//类说明:启动方法类,用于启动读写线程
public class testQueue{
   
	//设置队列容量为5个
	private final smallQueue<Order> smallQueue = new smallQueue<Order>(5);
	public static void main(String[] args) {
   
		testQueue testQueue = new testQueue();
		for(int i=0;i<20;i++){
   //创建20个读线程
			new Thread(new readQueue(testQueue.smallQueue)).start();
		}
		//创建一个写线程
		new Thread(new writeQueue(testQueue.smallQueue)).start();
	}
}

  • readQueue类代码:
package queue;

import java.util.concurrent.TimeUnit;

import testDemo.Order;

public class readQueue implements Runnable{
   
	private final smallQueue<Order> smallQueue;
	public readQueue(smallQueue<Order> smallQueue){
   
		this.smallQueue = smallQueue;
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值