分析内存溢出:
线程池是长生命周期的,而线程是执行完任务线程就结束了(线程相关资源就会释放)
问题1:Hashmap和ThreadLocalMap处理hash冲突的区别?
答:Hashmap使用的链表法,ThreadLocalMap使用开放寻址法
原因:开放寻址法的特点和使用场景是数据量比较少的情况下性能更好;而Hashmap里面存储的数据通常情况下是比较多,此时最好使用链式法
问题2:为什么会发生OOM?
答:ThreadPool(长生命周期)----》Thread–>ThreadLocalMap—>Entry[ ]–>Entry—>key,value(强引用)
问题3:如何解决ThreadLocal的内存溢出? 答:使用remove()
链表->红黑树
升级:
1.链表长度大于8;
2.数组的长度大于64.
降级(红黑树->链表) :
当链表的长度小于6的时 候。
提升程序的性能:
1.多线程
2.单例模式:整个程序的运行中只存储一个对象
- 饿汉方式:
- 优点:线程安全
- 缺点:程序启动之后就会创建,但是创建完了之后有可能不会使用,从而浪费系统资源
class Singleton{
//1.创建私有构造函数(防止其他类直接创建)
private Singleton(){
}
//2.定义私有变量(线程安全)
private static Singleton singleton = new Singleton();
//3.提供公共的获取实例的方法
public static Singleton getInstance(){
return singleton;
}
}
- 懒汉方式:当程序启动之后并不会进行初始化,而是什么时候调用什么时候初始化
非安全的单例模式如下:
/**
* 懒汉方式
* 版本一
* 非安全的单例模式-懒汉
*/
public class ThreadDemo2 {
static class Singleton{
//1.创建一个私有的构造函数(防止其他地方直接实例化)
private Singleton(){
}
//2.创建一个私有的类对象
private static Singleton singleton = null;
//3.提供统一的访问入口(方法)
public static Singleton getInstance(){
if (singleton==null){
//第一次访问
singleton = new Singleton();
}
return singleton;
}
}
public static void main(String[] args) {
//创建第一个对象
Singleton s1 = Singleton.getInstance();
//创建第二个对象
Singleton s2 = Singleton.getInstance();
System.out.println(s1==s2);
}
}
线程不安全的解决方案:
1.加锁
2. ThreadLocal
设计模式(了解):
1.单例模式(手写)
链表相关;翻转;简单的排序算法;死锁;单例模式
2.工厂模式(简单工厂,抽象工厂)
3.模板模式 。。。
饿汉方式:
优点:线程安全
缺点:程序启动之后就会创建,但是创建完了之后有可能不会使用,从而浪费系统资源
懒汉方式:当程序启动之后并不会进行初始化,而是什么时候调用什么时候初始化
* 懒汉方式
* 版本一
* 非安全的单例模式-懒汉
*/
public class ThreadDemo2 {
static class Singleton{
//1.创建一个私有的构造函数(防止其他地方直接实例化)
private Singleton()