1.慎用延迟初始化
1.1 什么是延迟初始化?
延迟初始化:指延迟到需要域的值的时候,才将它初始化的行为。
这是一种性能优化,可以提高性能,降低开销。不过延迟初始化是把双刃剑。它可能会破坏线程安全。
所以在大部分情况下,正常的初始化要优先于延迟初始化。
1.2 对静态域进行延迟初始化
对静态域使用延迟初始化,可以使用lazy initialization holder class模式。
简单来说就是静态内部类,属于单例模式的一种。
定义静态方法,引用外部类的静态成员域。当第一次调用时
public class InitMain {
public static void main(String[] args){
staticInit a= staticInit.getInstance();
}
}
public class staticInit {
staticInit() {
System.out.println("构造函数");
}
//类级内部类,也就是静态的成员内部类,该内部类的实例与外部类的实例没有绑定关系,
//而且只有调用的时候才会装载,从而实现了延迟加载
private static class SingletonHolder{
//静态初始化器,由JVM保证线程安全
private static staticInit instance = new staticInit();
}
public static staticInit getInstance() {
System.out.println("沙丁鱼获取了实例");
return SingletonHolder.instance;
}
}
1.3 对实例域进行延迟初始化
对实例域使用延迟初始化,可以使用双重检查模式(double check idiom)。
这种模式需要两次检查域的值,所以叫双重检查。
第一次检查没有锁定,查看域是否初始化,第二次检查有锁定。
只有当第二次检查无初始化时,才会初始化。当初始化后,域就不会被锁定了,所以volatile修饰比较重要。
2.不要依赖于线程调度器
这一节是对线程使用的一些忠告。
2.1.不要依赖于线程调度器
线程调度器是什么?
线程调度器是一个操作系统服务,它负责为 Runnable 状态的线程分配 CPU 时间。所以注意了!,它是一个操作系统服务,所以它是很大可能不可移植的,因为操作系统很多电脑并不同。
所以线程不要依赖于线程调度器。
2.2 保持尽可能少的可运行线程数量
这一点其实和性能有关,尽可能少的线程数量可以提高性能。所以如果线程在做无意义的工作的话,就不应该运行。
这里提供的解决方法是FixedExecutor 线程池,限制线程数量。使用CountDownLatch进行实现。
2.3 线程优先级是java最不可移植的特征
如题目,线程优先级虽然可以改善线程性能,但是线程优先级之前也讲过,是和操作系统挂钩的。
之前关于优先级的笔记
https://blog.csdn.net/asdfghj253/article/details/104050967