在HashMapService类中定义了一个HashMap的成员变量,在add方法中往HashMap中添加数据 。在controller层的接口中调用add方法,会使用tomcat的线程池去处理请求,就相当于在多线程的场景下调用add方法 。
在jdk1.7中,HashMap使用的数据结构是:数组+链表 。如果在多线程的情况下,不断往HashMap中添加数据,它会调用resize方法进行扩容 。该方法在复制元素到新数组时,采用的头插法,在某些情况下,会导致链表会出现死循环 。
死循环最终结果会导致:内存溢出 。
此外,如果HashMap中数据非常多,会导致链表很长 。当查找某个元素时,需要遍历某个链表,查询效率不太高 。
为此,jdk1.8之后,将HashMap的数据结构改成了:数组+链表+红黑树 。
如果同一个数组元素中的数据项小于8个,则还是用链表保存数据 。如果大于8个,则自动转换成红黑树 。
为什么要用红黑树?
答:链表的时间复杂度是O(n),而红黑树的时间复杂度是O(logn),红黑树的复杂度是优于链表的 。
既然这样,为什么不直接使用红黑树?
答:树节点所占存储空间是链表节点的两倍,节点少的时候,尽管在时间复杂度上,红黑树比链表稍微好一些 。但是由于红黑树所占空间比较大,HashMap综合考虑之后,认为节点数量少的时候用占存储空间更多的红黑树不划算 。
jdk1.8中HashMap就不会出现死循环?
答:错,它在多线程环境中依然会出现死循环 。在扩容的过程中,在链表转换为树的时候,for循环一直无法跳出,从而导致死循环 。
那么,如果想多线程环境中使用HashMap该怎么办呢?
答:使用ConcurrentHashMap 。
7. 使用默认线程池我们都知道jdk1.5之后,提供了ThreadPoolExecutor类,用它可以自定义线程池 。
线程池的好处有很多,比如:
- 降低资源消耗:避免了频繁的创建线程和销毁线程,可以直接复用已有线程 。而我们都知道,创建线程是非常耗时的操作 。
- 提供速度:任务过来之后,因为线程已存在,可以拿来直接使用 。
- 提高线程的可管理性:线程是非常宝贵的资源,如果创建过多的线程,不仅会消耗系统资源,甚至会影响系统的稳定 。使用线程池,可以非常方便的创建、管理和监控线程 。
该类中包含了很多静态方法:
- newCachedThreadPool:创建一个可缓冲的线程,如果线程池大小超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程 。
- newFixedThreadPool:创建一个固定大小的线程池,如果任务数量超过线程池大小,则将多余的任务放到队列中 。
- newScheduledThreadPool:创建一个固定大小,并且能执行定时周期任务的线程池 。
- newSingleThreadExecutor:创建只有一个线程的线程池,保证所有的任务安装顺序执行 。
那么,我们一起看看有哪些问题?
- newFixedThreadPool:允许请求的队列长度是Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM 。
- newSingleThreadExecutor:允许请求的队列长度是Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM 。
- newCachedThreadPool:允许创建的线程数是Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM 。
优先推荐使用ThreadPoolExecutor类,我们自定义线程池 。
具体代码如下:
ExecutorService threadPool = new ThreadPoolExecutor(8, //corePoolSize线程池中核心线程数10, //maximumPoolSize 线程池中最大线程数60, //线程池中线程的最大空闲时间,超过这个时间空闲线程将被回收TimeUnit.SECONDS,//时间单位new ArrayBlockingQueue(500), //队列new ThreadPoolExecutor.CallerRunsPolicy()); //拒绝策略
顺便说一下,如果是一些低并发场景,使用Executors类创建线程池也未尝不可,也不能完全一棍子打死 。在这些低并发场景下,很难出现OOM问题,所以我们需要根据实际业务场景选择 。8. @Async注解的陷阱之前在java并发编程中实现异步功能,一般是需要使用线程或者线程池 。
线程池的底层也是用的线程 。
而实现一个线程,要么继承Thread类,要么实现Runnable接口,然后在run方法中写具体的业务逻辑代码 。
推荐阅读
- 聊聊 HTTP/2 的多路复用
- 糖尿病|肥胖可能引起糖尿病等50多种并发症!老人也能减肥缓解慢性病
- 聊聊Mybatis的binding模块
- 聊聊|炉石传说:是时候来聊聊这版本最脏职业到底是谁了
- 大学生|传奇世界:聊聊三职业终极技能,每一个都是经典!(上)
- 一个程序小BUG产生的原因
- 今日全民健身日,聊聊你不知道的健身锻炼冷知识
- 从三点进行分析说明,零基础看完也能明白 学习编程有什么用
- 创始人是王思聪,聊聊ig那些事 ig战队是王思聪的吗?
- 月经量少有哪些并发症?月经量少的患者应避免饮食