Java并发编程(十六)-JUC Collections
参考文献
JUC Collections 集合框架
Queue
Blocking Queue阻塞队列
java.util.concurrent.ArrayBlockingQueue:最基础且开发中最常用的阻塞队列,底层采用数组实现的有界队列,初始化需要指定队列的容量.
ArrayBlockingQueue 是如何保证线程安全的呢?它内部是使用了一个重入锁ReentrantLock,并搭配 notEmpty、notFull 两个条件变量Condition来控制并发访问.从队列读取数据时,如果队列为空,那么会阻塞等待,直到队列有数据了才会被唤醒.如果队列已经满了,也同样会进入阻塞状态,直到队列有空闲才会被唤醒.
java.util.concurrent.LinkedBlockingQueue:内部采用的数据结构是链表,队列的长度可以是有界或者无界的.
初始化不需要指定队列长度,默认是Integer.MAX_VALUE.LinkedBlockingQueue 内部使用了takeLock、putLock两个重入锁ReentrantLock,以及notEmpty、notFull两 ...
Java Array
参考文献
Arrays
数组长度
所使用的排序算法
length < 47
插入排序
47 <= length < 286
快速排序
length >= 28
归并排序
length >= 286
快速排序
JWT
参考文献
了解 JWT Token 释义及使用
JSON Web Algorithms (JWA)
JWT 简介、陷阱及建议
JSON Web Token Best Current Practices
概念
JSON Web Token (JWT,RFC 7519),是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519)。该 token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 token 也可直接被用于认证,也可被加密。
使用场景
授权:这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小并且能够轻松地跨不同域使用。
信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。因为 JWT 可以进行签名(例如,使用公钥/私钥对 ...
JavaNIO-Socket
参考文献
非阻塞 vs 阻塞
阻塞
阻塞模式下,相关方法都会导致线程暂停
ServerSocketChannel.accept 会在没有连接建立时让线程暂停
SocketChannel.read 会在没有数据可读时让线程暂停
阻塞的表现其实就是线程暂停了,暂停期间不会占用 cpu,但线程相当于闲置
单线程下,阻塞方法之间相互影响,几乎不能正常工作,需要多线程支持
但多线程下,有新的问题,体现在以下方面
32 位 jvm一个线程 320k,64 位 jvm 一个线程1024k,如果连接数过多,必然导致 OOM,并且线程太多,反而会因为频繁上下文切换导致性能降低
可以采用线程池技术来减少线程数和线程上下文切换,但治标不治本,如果有很多连接建立,但长时间inactive,会阻塞线程池中所有线程,因此不适合长连接,只适合短连接.
服务器端
123456789101112131415161718192021222324252627// 使用 nio 来理解阻塞模式, 单线程// 0. ByteBufferByteBuffer buffer = ByteBuffer.allocat ...
JavaNIO-ByteBuffer
参考文献
黑马Netty
Buffer(缓冲区)
Buffer是一个对象,它包含一些要写入或者要读出的数据.在面向流的I/O中,可以将数据直接写入或者将数据直接读到Stream对象中.
在NIO库中,所有数据都是用缓冲区处理的.在读取数据时,它是直接读到缓冲区中的;在写入数据时,写入到缓冲区中.任何时候访问NIO中的数据,都是通过缓冲区进行操作.
缓冲区实质上是一个数组.通常它是一个字节数组(ByteBuffer),也可以使用其他种类的数组.但是缓冲区不仅仅是一个数组,缓冲区提供了对数据的结构化访问以及维护读写位置(limit)等信息.
最常用的缓冲区是ByteBuffer,一个ByteBuffer提供了一组功能用于操作byte数组.除了ByteBuffer,还有其他的一些缓冲区,事实上,每一种Java基本类型(除了Boolean类型),都有与之对应的缓冲区:
类型
说明
ByteBuffer
字节缓冲区
CharBuffer
字符缓冲区
ShortBuffer
短整形缓冲区
IntBuffer
整形缓冲区
LongBuffer
长整型 ...
Java日志框架
参考文献
SLF4J user manual
Slf4j
简单使用
12slf4j-api-${version}.jarslf4j-simple-${version}.jar
12345678910<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> ...
JDK8特性-新的日期和时间API
参考文献
Convert between Date to LocalDateTime
旧的日期和时间API的缺点
Date类的缺点
Date类中的大多数方法都已经过时,因为它们不是线程安全的,而且有一些设计缺陷.
Date类中的时间表示是基于1970年1月1日的毫秒数,这种表示方式不太方便处理日期和时间.
Calendar类的缺点
Calendar类不是线程安全的,如果多个线程同时访问一个Calendar实例,可能会导致不可预测的结果.
Calendar类中的月份是从0开始计数的,这种设计很容易导致错误.
Calendar类中的方法名不够直观,比如要设置月份要使用set(Calendar.MONTH, month),而不是setMonth(month).
DateFormat类的缺点
DateFormat类不是线程安全的,如果多个线程同时访问一个DateFormat实例,可能会导致不可预测的结果.
DateFormat类中的解析和格式化方法都很慢,因为它们需要进行字符串和日期之间的转换.
新的日期和时间API
java.time包的类
123456789101112 ...
JDK8特性-default方法
参考文献
Java8实战
解决问题的三条规则
如果一个类使用相同的函数签名从多个地方(比如另一个类或接口)继承了方法,通过三条规则可以进行判断.
类中的方法优先级最高.类或父类中声明的方法的优先级高于任何声明为默认方法的优先级.
如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体.
1234567891011121314151617181920package com.holelin.sundry.test.common;public interface A { default void hello() { System.out.println("Hello from A"); }}interface B extends A { default void hello() { System.out.println("Hello from B&qu ...
Java并发源码分析-ConcurrentHashMap源码分析
参考文献
面试 ConcurrentHashMap ,看这一篇就够了!
ConcurrentHashMap
JDK1.7
在 JDK1.7 中,ConcurrentHashMap 使用了分段锁的机制,将哈希表分为多个 Segment,每个 Segment 上都有一把锁,不同的 Segment 可以被不同的线程同时访问,这样可以提高并发度,减少锁的争用。
每个 Segment 内部使用一个 HashEntry 数组来存储元素,每个 HashEntry 都是一个链表的头节点,通过链表的方式解决哈希冲突。这种数据结构的设计使得并发情况下,只有访问同一个 Segment 上的元素才需要加锁,其他 Segment 上的元素可以并发访问,提高了并发度。
JDK1.8之后
在 JDK1.8 中,ConcurrentHashMap 放弃了 Segment 分段锁的机制,采用了与HashMap相同的Node 数组+链表+红黑树的结构。这样可以减少了锁的竞争,提高了并发度,同时也减少了内存占用。
在 JDK1.8 中,ConcurrentHashMap 使用了CAS +synchroniz ...