在做我的开源项目:IceoLogy壁纸时,第二版加入了屏保之后,内存竟然要用到800多M,稳定运行到900M,我自己都不敢相信自己的眼睛,就4个页面而已啊,我的代码还不至于这么烂吧。但现实就摆在眼前,这肯定是不行的,一般的家用电脑就4G的内存,用上我这个壁纸还不得卡死了,不知道的还以为我写的病毒呢,作为一个有职业素养的程序员,怎么能从自己的手上放任这种事情来毁掉自己的一世英名呢。
于是就加入了漫长的优化之路,几乎把代码都重构了,但内存还是居高不下,但是我看到SecretOpen的 开源secret-performance-desktop,这么炫酷的特效竟然只有用到了300M,瞬间对大佬的仰望角度又多了90°,经过了对大佬代码的研究发现使用了单例工厂初始化Stage,重点是工厂中使用了弱引用(WeakReference),使内存回收gc能够快速回收内存。经过一周的奋战,终于优化到了300多M。
为了更好的帮助踩坑的各位,恰好和secret-performance-desktop的开源者secret、是企鹅好友,在征得大佬的同意后,现在将源码开源,相信java会越来越好,大家都秉着这种开源的态度,我们这个圈子也会越来越好。
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: 单例工厂
* @author secret
* @date 2021/1/5 19:43
*
*/
public class SingletonFactory {
@SuppressWarnings("rawtypes")
private static Map<Class,Object> instaces = new ConcurrentHashMap<Class, Object>();
@SuppressWarnings("rawtypes")
private static Map<Class,WeakReference<Object>> weakReferenceInstaces = new ConcurrentHashMap<Class, WeakReference<Object>>();
/**
* 创建可不被回收的单例模式,当没有对象引用,单例对象将被gc掉
* @param className
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
@SuppressWarnings("unchecked")
public static <E> E getInstace(Class<E> className){
Object instace =instaces.get(className);
if(instace==null){
synchronized (SingletonFactory.class) {
instace =instaces.get(className);
if(instace==null){
try {
instace = className.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
instaces.put(className,instace);
}
}
}
return (E)instace;
}
/**
* 创建可回收的单例模式,当没有对象引用,单例对象将被gc掉
*
* @param className
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
@SuppressWarnings("unchecked")
public static <E> E getWeakInstace(Class<E> className) {
WeakReference<Object> reference = weakReferenceInstaces.get(className);
Object instace =reference==null?null:reference.get();
if(instace==null){
synchronized (SingletonFactory.class) {
reference = weakReferenceInstaces.get(className);
instace =reference==null?null:reference.get();
if(instace==null){
try {
instace = className.getDeclaredConstructor().newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
weakReferenceInstaces.put(className,new WeakReference<Object>(instace));
}
}
}
return (E)instace;
}
}
使用方法:每个页面Stage都实现一个初始示例化方法,调用SingletonFactory.getWeakInstace()单例工厂方法来初始化页面,其他需要使用的地方都调用这个实例化方法。如下:
原理:利用弱引用让gc回收掉内存
最后感谢javafx社区:让我们很多喜欢Javafx的同业在这里汇聚,社区qq群:526035097,也比较活跃,我也会提问,回答。