东莞市盛裕绒艺玩具有限公司

东莞市盛裕绒艺玩具有限公司

wellbet不给提款

15308085745
联系方式
全国服务热线: 15308085745

咨询热线:18521199588
联系人:胡海涛
地址:宁波市北仑区长江国际商务大厦B座1105室

挑战常规--这样写单例是错的!

来源:wellbet不给提款   发布时间:2019-06-26   点击量:42

说到单例,网上教程和很多人信手拈来:

public class Single{private volatile static Single instance;private Single(){System.out.println("创建单例");} public static Single getInstance(){if (instance == null){synchronized (Single.class){if (instance == null){instance = new Single();}}}return instance;}}

 自信满满,称之为懒汉加载模式言之节省内存,用时才会自动创建。在我看来,这种写法完全是错误的,愚蠢至极,这不是脱裤子放屁,这是脱完裤子再提取裤子再放屁。

正确写法就是最简单的:

public class Single{private static Single instance=new Single();private Single(){System.out.println("创建单例");} public static Single getInstance(){ return instance;}}

 

下面驳斥所谓的省内存。

public class SingleTest{ public static void main(String[] args) throws Exception{ System.out.println("启动线程");System.in.read();}}

 首先,不用单例时,难道别的写法就会加载单例?没有引用使用单例类时,当然都不会加载单例。

看图,并不会加载创建单例,控制台也不会输出创建单例。

其次,既然预定要使用单例,那么都会加载创建一次。

public class SingleTest{ public static void main(String[] args) throws Exception{ System.out.println("启动线程");Single.getInstance();System.in.read();}}

 看图,无论哪种模式单例都会被引用加载

 

是不是用synchronized创建单例就没有用处了呢?

并不是synchronized是用于解决多线程访问问题带参数的单例创建才应该使用懒汉模式

因为并不能预期,什么时候参数被传入。简单模式下并不清楚传入什么参数,或参数对象未初始化。

 

public class Single{private volatile static Single instance ; public Single(Context context){System.out.println("创建单例");}public static Single getInstance(Context context){if (instance == null){synchronized (Single.class){if (instance == null){instance = new Single(context);}}}return instance;}}

 

 为什么说这个是为了解决多线程访问呢,先看如果不加锁会发生什么

public class Single{ private static Single instance ; public Single(Context context) { System.out.println("创建单例"); } public static Single getInstance(Context context) { if (instance == null) { instance = new Single(context); } return instance; }}

public class SingleTest{public static void main(String[] args) throws Exception{ExecutorService pool = Executors.newCachedThreadPool();ArrayList<Callable<Void>> runners=new ArrayList<>();for(int i=0;i<10;i++){runners.add(()->{Single.getInstance(new Context());return null;});}System.out.println("启动线程");pool.invokeAll(runners);pool.shutdown();System.in.read();}}

 不加锁情况,结果看图

 

加锁情况,结果看图

 

总结,无参构造单例无需复杂的加入synchronized,而未确定的传参单例需要加synchronized保证多线程访问安全。

思考,如果传入的参数确定,怎么写才最优呢?下面类似写法是否合理:

 

public class Single{private static Single instance =new Single(Context.instance); public Single(Context context ){System.out.println("创建单例");}public static Single getInstance( ){ return instance;}}

 

 

@WebListenerpublic class MyServletContextListener implements ServletContextListener { public void contextDestroyed(ServletContextEvent sce) { } public void contextInitialized(ServletContextEvent sce) { Single.getInstance(sce); } }

 

相关产品

COPYRIGHTS©2017 wellbet不给提款 ALL RIGHTS RESERVED 备案号:42