今天学了下面这几样
collection接口Map接口集合实现线程安全线程的原子性、可见性、有序性新建线程的方式线程池的种类以及特点线程池的拒绝策略
collection接口
collection接口的主要有两个子接口,分别为List和Set。
-
List接口
List接口是有序对象集合,主要有三个实现类,分别为ArrayList、LinkedList、Vector。
-
ArrayList底层由数组实现,查找元素复杂度为O(1),增删元素涉及到数组扩容和拷贝元素,时间复杂度为O(n)。每次扩容1.5倍。
-
LinkedList底层由链表实现,查找元素复杂度为O(n),增删元素时间复杂度为O(1)。
-
Vector与ArrayList几乎一样,不过因为考虑了线程安全,所以会稍慢一点。
-
Set接口
Set接口是无序不重复对象集合,不过它的实现类TreeSet实现了SortedSet接口,通过Comparator或Comparable维护排序顺序实现了有序Set。主要实现类有HashSet、LinkedHashSet、TreeSet。
-
HashSet由HashMap实现,允许有Null元素出现,查找时间复杂度为 O(1) ,默认加载因子为0.75,最大容量为16。
-
LinkedHashSet由LinkedHashMap实现,允许有Null元素出现,查找时间复杂度为 O(1) ,因为除了使用哈希表存储数据,还使用了一条双向链表,所以在需要遍历的场景中速度会更快一点。默认加载因子为0.75,最大容量为16。
-
TreeSet由TreeMap实现,不允许有Null出现,其内部元素有序,可按照自然排序也可根据使用的比较器排序,操作时间复杂度为 O(log n)。
Map接口
Map为键值对对象集合,其中每一个对象都有两个属性,分别为key和value,可能会有多个相同的value,但是相同的key只能同时存在一个。其主要实现类主要有HashMap、LinedHashMap、HashTable和TreeMap。
HashMap
-
底层实现:jdk1.7以前是由数组加链表实现,jdk1.8及以后是通过数组加链表/红黑树实现,当链表长度大于8的时候链表转化为红黑树,小于6的时候转为链表。
-
为何使用数组:因为查找速度快,并且HashMap中扩容机制是2倍,ArrayList中是1.5倍。
-
是否允许为空:key和value都允许为空。
-
扩容机制:每次扩容2倍。
LinedHashMap
在HashMap的基础上添加了一条双向链表维护顺序,保证了在迭代的时候元素的有序性。
HashTable
与HashMap区别不大,不过保证了线程安全,效率稍低。同时key与value不允许为空。底层数组长度可以为任意数值,默认为11。(不推荐使用)
TreeMap
TreeMap由红黑树实现,同时实现了SortedMap接口,保证了元素的有序性。key和value允许为空,
集合实现线程安全
-
使用synchronize或Lock加锁以此保证线程安全。(速度慢)
-
使用ConcurrentHashMap实现线程安全,速度也快。底层主要通过CAS和volatile还有synchronize实现,初始化状态由volatile+CAS解决。
线程的原子性、可见性、有序性
-
原子性:同一时间只能由一个线程对当前数据进行操作。
-
可见性:当前数据被线程修改时,其他线程应当可以及时观察到。
-
有序性:如果两个线程不能通过happens-before原则观察顺序,那么虚拟机可以对其进行任意重排序,则应当遵循happens-before原则。
新建线程的方式
-
通过继承Thread类创建.
-
实现Runnable接口创建线程。
-
通过线程池创建线程。
-
通过Callable和Future可以创建有返回值的线程。
线程池的种类以及特点
-
Single Thread Executor线程池:线程池中只有一个线程,当一个线程结束会新创建一个线程继续执行。适用于多任务线性执行的情况。
-
Cached Thread Pool线程池:可缓存的线程池,当线程池的任务小于规模时,会自动回收对于线程,当线程池的任务多于规模的时候,会自动创建新的线程。极端情况下会 创建过多的线程,耗尽 CPU 和内存资源 ,适用于大批量,处理速度快的任务。
-
Fixed Thread Pool线程池:固定线程数的线程池,空闲时线程会一直等待。适用于需要长期执行的任务。
-
Schedule Thread Pool线程池:固定长度的线程池,以延迟或定时的方式执行任务。适用于周期性执行的任务。
线程池的拒绝策略
-
CallerRunPolicy:当有新的任务提交以后,如果线程池没有能力只执行,那就让提交任务的线程去执行。
-
AbortPolicy:直接抛出RejectedExecutionException异常,可以让开发直接获取到拒绝状态,能够根据业务去重试或者丢弃任务。
-
DiscardPolicy:直接丢弃任务,此方式有一定风险,因为无法感知到任务到底是被执行还是丢弃。
-
DiscardOldestPolity:丢弃当前队列中最老的任务,与上一种不同之处在于丢弃的是存活时间最长的任务,同样,他也有丢失数据的风险。
本文使用 文章同步助手 同步
网友评论