java8多线程、队列集合和线程池
1. 线程的取消和中断
- interrupt() 中断线程,本质是将线程的中断标志位设为true,其他线程向需要中断的线程打个招呼。是否真正进行中断由线程自己决定
- isInterrupted() 线程检查自己的中断标志位
- 静态方法Thread.interrupted() 将中断标志位复位为false
2. volatile
Violate修饰字段,对这个变量的访问必须要从共享内存刷新一次。最新的修改写回共享内存。可以保证字段的可见性。绝对不是线程安全的,没有操作的原子性。
- putIfAbsent(key,value)方法原子性
如果key对应的value不存在,则put进去,返回null。否则不put,返回已存在的value。
- boolean remove(Object key, Object value)
如果key对应的值是value,则移除K-V,返回true。否则不移除,返回false。
- boolean replace(K key, V oldValue, V newValue)
如果key对应的当前值是oldValue,则替换为newValue,返回true。否则不替换,返回false。
5. ConcurrentSkipListMap TreeMap的并发实现 跳跃表其实也是一种通过“空间来换取时间”的一个算法,通过在每个节点中增加了向前的指针,从而提升查找的效率。
ConcurrentSkipListSet TreeSet的并发实现
CopyOnWriteArrayList 写操作的时候复制,当有新元素添加到CopyOnWriteArrayList的时候,先从原有数组里面拷贝一份出来,然后在新的数组做写操作,最后将原有的数组指向新的数组,是线程安全的,整个add操作都是在锁的机制下操作的。缺点一是由于写操作需要拷贝数组,消耗内存,缺点二,不适合实时读的场景。CopyOnWriteArrayList适合读多写少的场景。CopyOnWriteArrayList特点是读写分离、最终一致性、使用时另外开辟空间,解决并发冲突。CopyOnWriteArrayList的读操作都是在原数组读取的,不需要加锁的,写操作是需要加锁的。
方法 | 抛出异常 | 返回值 | 一直阻塞 | 超时退出 |
---|---|---|---|---|
插入 | Add | offer | put | offer |
移除 | remove | poll | take | poll |
检查 | element | peek | 没有 | 没有 |
ArrayBlockingQueue 数组结构组成有界阻塞队列,先进先出原则,初始化必须传大小,take和put时候用的同一把锁。
LinkedBlockingQueue 链表结构组成的有界双向阻塞队列,先进先出原则,可以在队列的两端插入和移除,xxxFirst头部操作,xxxLast尾部操作。初始化可以不传大小,put,take锁分离。
PriorityBlockingQueue 支持优先级排序的无界阻塞队列,自然顺序升序排列,更改顺序:类自己实现compareTo()方法,初始化PriorityBlockingQueue指定一个比较器Comparator
DelayQueue 使用了优先级队列的无界阻塞队列,支持延时获取,队列里的元素要实现Delay接口。DelayQueue非常有用,可以将DelayQueue运用在以下应用场景:
缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。还有订单到期,限时支付等.
1.客户端长时间占用连接的问题,超过这个空闲时间了,可以移除的
2.处理长时间不用的缓存:如果队列里面的对象长时间不用,超过空闲时间,就移除
3.任务超时处理
SynchronousQueue 不存储元素的阻塞队列,每个put操作必须要等take操作
LinkedTransferQueue 链表结构组成的无界阻塞队列,Transfer,tryTransfer,生产者put时,当前有消费者take,生产者直接把元素传给消费者
7. CyclicBarrier和CountDownLatch的区别
CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重
置,CountDownLatch.await一般阻塞主线程,所有的工作线程执行countDown,而CyclicBarrierton通过工作线程调用await从而阻塞工作线程,直到所有工作线程达到屏障。
CyclicBarrier可以用于多线程计算数据,最后合并计算结果的场景。