说到单例OA信用盘源码出售QQ2952777280【话仙源码论坛】hxforum.com,网上教程和很多人信手拈来:
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;
}
}
复制代码br/>@WebListener
public class MyServletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent sce) {
}
public void contextInitialized(ServletContextEvent sce) {
Single.getInstance(sce);
}
}