1. 如何写一个简单的单例模式
一、基本的实现思路:
单例的实现主要是通过以下两个步骤:
1、将该类的构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例;
2、在该类内提供一个静态方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用。
二、示范如下:
1、枚举实现单例:
2、懒汉式线程不安全:
3、懒汉式线程安全:
4、饿汉式:
5、双重校验锁:
6、静态内部类:
扩展资料:
一、单列模式简介:
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
二、懒汉与饿汉:
1、懒汉方式:指全局的单例实例在第一次被使用时构建。
2、饿汉方式:指全局的单例实例在类装载时构建。
三、单例模式的三要点:
1、某个类只能有一个实例。
2、它必须自行创建这个实例。
3、它必须自行向整个系统提供这个实例。
四、优缺点:
1、优点:
①实例控制:单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
②灵活性:因为类控制了实例化过程,所以类可以灵活更改实例化过程。
2、缺点:
①开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
②可能的开发混淆:使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
③对象生存期:不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
参考资料:百度百科单列模式
2. 如何写一个简单的单例模式
单例模式的要点有三个;一是某各类只能有一个实例;二是它必须自行创建这个事例;三是它必须自行向整个系统提供这个实例。
单例模式有以下的特点:
1 单例类只可有一个实例。
2 单例类必须自己创建自己这惟一的实例。
3 单例类必须给所有其他对象提供这一实例。
public class EagerSingleton
{
private static final EagerSingleton m_instance =
new EagerSingleton();
/**
* 私有的默认构造子
*/
private EagerSingleton() { }
/**
* 静态工厂方法
*/
public static EagerSingleton getInstance()
{
return m_instance;
}
}
在这个类被加载时,静态变量m_instance 会被初始化,此时类的私有构造子会被调用。这时候,单例类的惟一实例就被创建出来了。
楼主可以具体参阅 阎宏博士的《Java与模式》一书的第十五章
3. java几种单例模式写法
懒汉模式public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static SingletonDemo getInstance(){if(instance==null){instance=new SingletonDemo();}return instance;}}2. 线程安全的懒汉模式public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static synchronized SingletonDemo getInstance(){if(instance==null){instance=new SingletonDemo();}return instance;}}3. 饿汉模式public class SingletonDemo {private static SingletonDemo instance=new SingletonDemo();private SingletonDemo(){}public static SingletonDemo getInstance(){return instance;}}4. 静态类内部加载public class SingletonDemo {private static class SingletonHolder{private static SingletonDemo instance=new SingletonDemo();}private SingletonDemo(){System.out.println("Singleton has loaded");}public static SingletonDemo getInstance(){return SingletonHolder.instance;}}5.双重校验锁法public class SingletonDemo {private volatile static SingletonDemo instance;private SingletonDemo(){System.out.println("Singleton has loaded");}public static SingletonDemo getInstance(){if(instance==null){synchronized (SingletonDemo.class){if(instance==null){instance=new SingletonDemo();}}}return instance;}}。
4. android 几种单例模式的写法
先不论单例模式的写法,有些方面是相同的,比如都需要将唯一的对象设置为static的,都需要将构造方法private化,代码如下:public class MyInstance { private static MyInstance instance; private MyInstance(){}}第一种:最原始的单例模式,代码如下:public static MyInstance getInstance(){ if(instance==null){ instance=new MyInstance();} return instance;}多线程并发时,可能会出现重复new对象的情况,因此不提倡使用。
第二种:将整个方法块进行加锁,保证线程安全。public static synchronized MyInstance getInstance(){ if(instance==null){ instance=new MyInstance();} return instance;}这种代码下,每条线程都会依次进入方法块内部,虽然实现了单例,但是影响了运行效率,可以使用但是也不怎么提倡。
第三种:进一步优化的方法。public static MyInstance getsInstance(){ synchronized (MyInstance.class){ if(instance==null){ instance=new MyInstance(); return instance;}else{ return instance;}}}这种方式只是第二种方法的一种优化,但是优化有限。
(以下的几种方法比较推荐使用)第四种:双层判断加锁,效率影响小且保证了线程安全。public static MyInstance getsInstance() { if (instance == null) { synchronized (MyInstance.class) { if(instance==null){ instance=new MyInstance();}}} return instance;}这种方法是对第二种和第三种方法的进一步优化,比较推荐使用。
第五种:内部类实现单例,不用线程锁来实现效率的提升。public class MyInstance { private MyInstance() {} public static MyInstance getInstance(){ return MyInstanceHolder.instance;} private static class MyInstanceHolder{ private static MyInstance instance=new MyInstance();}}在内部类中new对象,再将内部类的对象返回,这种方法是使用了java中class加载时互斥的原理来实现了线程的安全。
不加线程锁也使得运行效率不会受到较大的影响。比较提倡。
5. 如何正确地写出单例模式
当被问到要实现一个单例模式时,很多人的第一反应是写出如下的代码,包括教科书上也是这样教我们的。
1234567891011public class Singleton {private static Singleton instance;private Singleton (){}public static Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}}这段代码简单明了,而且使用了懒加载模式,但是却存在致命的问题。当有多个线程并行调用 getInstance() 的时候,就会创建多个实例。
也就是说在多线程下不能正常工作。懒汉式,线程安全为了解决上面的问题,最简单的方法是将整个 getInstance() 方法设为同步(synchronized)。
123456public static synchronized Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}虽然做到了线程安全,并且解决了多实例的问题,但是它并不高效。因为在任何时候只能有一个线程调用 getInstance() 方法。
但是同步操作只需要在第一次调用时才被需要,即第一次创建单例实例对象时。这就引出了双重检验锁。
双重检验锁双重检验锁模式(double checked locking pattern),是一种使用同步块加锁的方法。程序员称其为双重检查锁,因为会有两次检查 instance == null ,一次是在同步块外,一次是在同步块内。
为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话就会生成多个实例了。12345678910public static Singleton getSingleton () {if (instance == null ) { //Single Checkedsynchronized (Singleton.class) {if (instance == null ) { //Double Checkedinstance = new Singleton();}}}return instance ;}这段代码看起来很完美,很可惜,它是有问题。
主要在于 instance = new Singleton() 这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情。给 instance 分配内存调用 Singleton 的构造函数来初始化成员变量将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)但是在 JVM 的即时编译器中存在指令重排序的优化。
也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。
我们只需要将 instance 变量声明成 volatile 就可以了。12345678910111213141516public class Singleton {private volatile static Singleton instance; //声明成 volatileprivate Singleton (){}public static Singleton getSingleton () {if (instance == null ) {synchronized (Singleton.class) {if (instance == null ) {instance = new Singleton();}}}return instance;}}有些人认为使用 volatile 的原因是可见性,也就是可以保证线程在本地不会存有 instance 的副本,每次都是去主内存中读取。
但其实是不对的。使用 volatile 的主要原因是其另一个特性:禁止指令重排序优化。
也就是说,在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。比如上面的例子,取操作必须在执行完 1-2-3 之后或者 1-3-2 之后,不存在执行到 1-3 然后取到值的情况。
从「先行发生原则」的角度理解的话,就是对于一个 volatile 变量的写操作都先行发生于后面对这个变量的读操作(这里的“后面”是时间上的先后顺序)。但是特别注意在 Java 5 以前的版本使用了 volatile 的双检锁还是有问题的。
其原因是 Java 5 以前的 JMM (Java 内存模型)是存在缺陷的,即时将变量声明成 volatile 也不能完全避免重排序,主要是 volatile 变量前后的代码仍然存在重排序问题。这个 volatile 屏蔽重排序的问题在 Java 5 中才得以修复,所以在这之后才可以放心使用 volatile。
相信你不会喜欢这种复杂又隐含问题的方式,当然我们有更好的实现线程安全的单例模式的办法。饿汉式 static final field这种方法非常简单,因为单例的实例被声明成 static 和 final 变量了,在第一次加载类到内存中时就会初始化,所以创建实例本身是线程安全的。
12345678910public class Singleton {//类加载时就初始化private static final Singleton instance = new Singleton();private Singleton (){}public static Singleton getInstance (){return instance;}}这种写法如果完美的话,就没必要在啰嗦那么多双检锁的问题了。缺点是它不是一种懒加载模式(lazy initialization),单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法。
饿汉式的创建方式在一些场景中将无法使用:譬如 Singleton 实例的创建是依赖参数或者配置文件的,在 getInstance() 之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。静态内部类 static nested class我比较倾向于使用静态内部类的方法,这种方法也是《Effective Java》上所推荐的。
123456789public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance () {return 。
6. 单例模式代码怎么写
单例模式(Singleton) ,属于最常见的设计模式之一,大部分系统都会用到,目的是为了维护系统中唯一的一个实例。
可分为eager模式,示例代码如下: Java代码 1.class EagerSingleton{ 2. private static final EagerSingleton m_instance = new EagerSingleton(); 3. private EagerSingleton(){} 4. public static EagerSingleton getInstance(){ 5. return m_instance; 6. } 7.} class EagerSingleton{ private static final EagerSingleton m_instance = new EagerSingleton(); private EagerSingleton(){} public static EagerSingleton getInstance(){ return m_instance; } } 和 lazy模式,示例代码如下: Java代码 1.class LazySingleton{ 2. private static LazySingleton m_instance = null; 3. private LazySingleton(){} 4. public synchronized static getInstance(){ 5. if(m_instance == null){ 6. m_instance = new LazySingleton(); 7. } 8. return m_instance; 9. } 10.} class LazySingleton{ private static LazySingleton m_instance = null; private LazySingleton(){} public synchronized static getInstance(){ if(m_instance == null){ m_instance = new LazySingleton(); } return m_instance; } } java源码中,Runtime.getRuntime()就是单例的一个例子。 单例模式的精神就是整个系统中维护一个实例,推广开来,如果在一个系统中需要维护多个示例,那么就产生了多例模式(multiton)。
多例模式(Multiton) ,通过聚集对象了保留自身的多个示例,根据客户端的参数返回所需要的实例。 示例代码如下: Java代码 1.class Multiton{ 2. private final int INSTANCE_SIZE = 10; 3. private static Map instances = new HashMap(INSTANCE_SIZE); 4. private String name; 5. private Multiton(){} 6. private Multiton(String name){ 7. this.name = name; 8. } 9. public synchronized static getInstance(String name){ 10. if(instances.containsKey(name)){ 11. return instances.get(name); 12. } 13. else{ 14. ins = new Multiton(name); 15. instances.put(name, ins); 16. return ins; 17. } 18. } 19.} class Multiton{ private final int INSTANCE_SIZE = 10; private static Map instances = new HashMap(INSTANCE_SIZE); private String name; private Multiton(){} private Multiton(String name){ this.name = name; } public synchronized static getInstance(String name){ if(instances.containsKey(name)){ return instances.get(name); } else{ ins = new Multiton(name); instances.put(name, ins); return ins; } } } [nextpage] 一个实用的例子就是KeyGenerator, 示例代码如下: Java代码 1.class KeyGenerator{ 2. private final int POOL_SIZE = 20; 3. private static Map instances = new HashMap(16); 4. private KeyInfo keyinfo; 5. private KeyGenerator(){} 6. private KeyGenerator(String keyName){ 7. this.keyinfo = new KeyInfo(POOL_SIZE, keyName); 8. } 9. public synchronized static getInstance(String keyName){ 10. if(instances.containsKey(keyName)){ 11. return (KeyGenerator)instances.get(keyName); 12. } 13. else{ 14. keyGen = new KeyGenerator(keyName); 15. instances.put(name, keyGen); 16. return keyGen; 17. } 18. } 19. public synzhronized int getNextKey(){ 20. return keyinfo.getNextKey(); 21. } 22. } class KeyGenerator{ private final int POOL_SIZE = 20; private static Map instances = new HashMap(16); private KeyInfo keyinfo; private KeyGenerator(){} private KeyGenerator(String keyName){ this.keyinfo = new KeyInfo(POOL_SIZE, keyName); } public synchronized static getInstance(String keyName){ if(instances.containsKey(keyName)){ return (KeyGenerator)instances.get(keyName); } else{ keyGen = new KeyGenerator(keyName); instances.put(name, keyGen); return keyGen; } } public synzhronized int getNextKey(){ return keyinfo.getNextKey(); } }。
7. 单例模式代码怎么写
单例模式(Singleton) ,属于最常见的设计模式之一,大部分系统都会用到,目的是为了维护系统中唯一的一个实例。
可分为eager模式,示例代码如下: Java代码 1.class EagerSingleton{ 2. private static final EagerSingleton m_instance = new EagerSingleton(); 3. private EagerSingleton(){} 4. public static EagerSingleton getInstance(){ 5. return m_instance; 6. } 7.} class EagerSingleton{ private static final EagerSingleton m_instance = new EagerSingleton(); private EagerSingleton(){} public static EagerSingleton getInstance(){ return m_instance; } } 和 lazy模式,示例代码如下: Java代码 1.class LazySingleton{ 2. private static LazySingleton m_instance = null; 3. private LazySingleton(){} 4. public synchronized static getInstance(){ 5. if(m_instance == null){ 6. m_instance = new LazySingleton(); 7. } 8. return m_instance; 9. } 10.} class LazySingleton{ private static LazySingleton m_instance = null; private LazySingleton(){} public synchronized static getInstance(){ if(m_instance == null){ m_instance = new LazySingleton(); } return m_instance; } } java源码中,Runtime.getRuntime()就是单例的一个例子。 单例模式的精神就是整个系统中维护一个实例,推广开来,如果在一个系统中需要维护多个示例,那么就产生了多例模式(multiton)。
多例模式(Multiton) ,通过聚集对象了保留自身的多个示例,根据客户端的参数返回所需要的实例。 示例代码如下: Java代码 1.class Multiton{ 2. private final int INSTANCE_SIZE = 10; 3. private static Map instances = new HashMap(INSTANCE_SIZE); 4. private String name; 5. private Multiton(){} 6. private Multiton(String name){ 7. this.name = name; 8. } 9. public synchronized static getInstance(String name){ 10. if(instances.containsKey(name)){ 11. return instances.get(name); 12. } 13. else{ 14. ins = new Multiton(name); 15. instances.put(name, ins); 16. return ins; 17. } 18. } 19.} class Multiton{ private final int INSTANCE_SIZE = 10; private static Map instances = new HashMap(INSTANCE_SIZE); private String name; private Multiton(){} private Multiton(String name){ this.name = name; } public synchronized static getInstance(String name){ if(instances.containsKey(name)){ return instances.get(name); } else{ ins = new Multiton(name); instances.put(name, ins); return ins; } } } [nextpage] 一个实用的例子就是KeyGenerator, 示例代码如下: Java代码 1.class KeyGenerator{ 2. private final int POOL_SIZE = 20; 3. private static Map instances = new HashMap(16); 4. private KeyInfo keyinfo; 5. private KeyGenerator(){} 6. private KeyGenerator(String keyName){ 7. this.keyinfo = new KeyInfo(POOL_SIZE, keyName); 8. } 9. public synchronized static getInstance(String keyName){ 10. if(instances.containsKey(keyName)){ 11. return (KeyGenerator)instances.get(keyName); 12. } 13. else{ 14. keyGen = new KeyGenerator(keyName); 15. instances.put(name, keyGen); 16. return keyGen; 17. } 18. } 19. public synzhronized int getNextKey(){ 20. return keyinfo.getNextKey(); 21. } 22. } class KeyGenerator{ private final int POOL_SIZE = 20; private static Map instances = new HashMap(16); private KeyInfo keyinfo; private KeyGenerator(){} private KeyGenerator(String keyName){ this.keyinfo = new KeyInfo(POOL_SIZE, keyName); } public synchronized static getInstance(String keyName){ if(instances.containsKey(keyName)){ return (KeyGenerator)instances.get(keyName); } else{ keyGen = new KeyGenerator(keyName); instances.put(name, keyGen); return keyGen; } } public synzhronized int getNextKey(){ return keyinfo.getNextKey(); } }。
8. 单例模式怎样写
class StringManager {
private static StringManager instance;
private Map beanMap;
private StringManager() {
beanMap = new HashMap();
}
public static StringManager getInstance() {
if (instance == null) {
instance = new StringManager();
}
return instance;
}
public Object getBean(String beanName) {
return beanMap.get(beanName);
}
}
9. 单例模式怎么写,求一份饿汉式单例 一份懒汉式单例
//懒汉式
public class A{
public static A a = null;
public A(){
}
public A getInstance(){
if(a==null){
return new A();
}
return a;
}
}
//饿汉式
public class A{
public static synchonized A a = new A();//线程安全
public A(){
}
public A getInstance(){
return a;
}
}
所谓饿就是急,无论需不需要先将单例对象给创建了,而懒汉式就是慢,需要的时候再创建,此外还有利用java缓存式的,利用内部类实现的单例模式,具体可以参考《清华大学出版社》出版的《研磨设计模式》