`
truelove12358
  • 浏览: 80015 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

java单例模式的线程安全

 
阅读更多


推荐使用:

多线程安全单例模式实例三(使用双重同步锁)


可以说单例模式是所有设计模式中最简单的一种。

单例模式就是说系统中对于某类的只能有一个对象,不可能出来第二个。

单例模式也是23中设计模式中在面试时少数几个会要求写代码的模式之一。主要考察的是多线程下面单例模式的线程安全性问题

1.多线程安全单例模式实例一(不使用同步锁)

复制代码
1 public class Singleton {
2     private static Singleton sin=new Singleton();    ///直接初始化一个实例对象
3     private Singleton(){    ///private类型的构造函数,保证其他类对象不能直接new一个该对象的实例
4     }
5     public static Singleton getSin(){    ///该类唯一的一个public方法    
6         return sin;
7     }
8 }
复制代码

  上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,当系统中这样的类较多时,会使得启动速度变慢 。现在流行的设计都是讲“延迟加载”,我们可以在第一次使用的时候才初始化第一个该类对象。所以这种适合在小系统。

2.多线程安全单例模式实例二(使用同步方法)

复制代码
 1 public class Singleton {  
 2      private static Singleton instance;  
 3      private Singleton (){
 4          
 5      }   
 6      public static synchronized Singleton getInstance(){    //对获取实例的方法进行同步
 7        if (instance == null)     
 8          instance = new Singleton(); 
 9        return instance;
10      }
11  }  
复制代码

  上述代码中的一次锁住了一个方法, 这个粒度有点大 ,改进就是只锁住其中的new语句就OK。就是所谓的“双重锁”机制。

3.多线程安全单例模式实例三(使用双重同步锁)

复制代码
 1 public class Singleton {  
 2      private static Singleton instance;  
 3      private Singleton (){
 4      }   
 5      public static Singleton getInstance(){    //对获取实例的方法进行同步
 6        if (instance == null){
 7            synchronized(Singleton.class){
 8                if (instance == null)
 9                    instance = new Singleton(); 
10            }
11        }
12        return instance;
13      }
14      
15  }
复制代码





以下是详细分析:


在所有的设计模式中,单例模式是我们在项目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一的告诉你答案,赶快来阅读吧!

什么是单例模式?

在文章开始之前我们还是有必要介绍一下什么是单例模式。单例模式是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种模式方法。

从概念中体现出了单例的一些特点:

(1)、在任何情况下,单例类永远只有一个实例存在

(2)、单例需要有能力为整个系统提供这一唯一实例


为了便于读者更好的理解这些概念,下面给出这么一段内容叙述:

在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

正是由于这个特点,单例对象通常作为程序中的存放配置信息的载体,因为它能保证其他对象读到一致的信息。例如在某个服务器程序中,该服务器的配置信息可能存放在数据库或文件中,这些配置数据由某个单例对象统一读取,服务进程中的其他对象如果要获取这些配置信息,只需访问该单例对象即可。这种方式极大地简化了在复杂环境 下,尤其是多线程环境下的配置管理,但是随着应用场景的不同,也可能带来一些同步问题。

各式各样的单例实现

温馨提示:本文叙述中涉及到的相关源码可以在这里进行下载源码,读者可免积分下载。

1、饿汉式单例

饿汉式单例是指在方法调用前,实例就已经创建好了。下面是实现代码:

  1. packageorg.mlinge.s01;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=newMySingleton();
  4. privateMySingleton(){}
  5. publicstaticMySingletongetInstance(){
  6. returninstance;
  7. }
  8. }
以上是单例的饿汉式实现,我们来看看饿汉式在多线程下的执行情况,给出一段多线程的执行代码:

  1. packageorg.mlinge.s01;
  2. publicclassMyThreadextendsThread{
  3. @Override
  4. publicvoidrun(){
  5. System.out.println(MySingleton.getInstance().hashCode());
  6. }
  7. publicstaticvoidmain(String[]args){
  8. MyThread[]mts=newMyThread[10];
  9. for(inti=0;i<mts.length;i++){
  10. mts[i]=newMyThread();
  11. }
  12. for(intj=0;j<mts.length;j++){
  13. mts[j].start();
  14. }
  15. }
  16. }

以上代码运行结果:

  1. 1718900954
  2. 1718900954
  3. 1718900954
  4. 1718900954
  5. 1718900954
  6. 1718900954
  7. 1718900954
  8. 1718900954
  9. 1718900954
  10. 1718900954

从运行结果可以看出实例变量额hashCode值一致,这说明对象是同一个,饿汉式单例实现了。

2、懒汉式单例

懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。下面是实现代码:

  1. packageorg.mlinge.s02;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=null;
  4. privateMySingleton(){}
  5. publicstaticMySingletongetInstance(){
  6. if(instance==null){//懒汉式
  7. instance=newMySingleton();
  8. }
  9. returninstance;
  10. }
  11. }
这里实现了懒汉式的单例,但是熟悉多线程并发编程的朋友应该可以看出,在多线程并发下这样的实现是无法保证实例实例唯一的,甚至可以说这样的失效是完全错误的,下面我们就来看一下多线程并发下的执行情况,这里为了看到效果,我们对上面的代码做一小点修改:

  1. packageorg.mlinge.s02;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=null;
  4. privateMySingleton(){}
  5. publicstaticMySingletongetInstance(){
  6. try{
  7. if(instance!=null){//懒汉式
  8. }else{
  9. //创建实例之前可能会有一些准备性的耗时工作
  10. Thread.sleep(300);
  11. instance=newMySingleton();
  12. }
  13. }catch(InterruptedExceptione){
  14. e.printStackTrace();
  15. }
  16. returninstance;
  17. }
  18. }
这里假设在创建实例前有一些准备性的耗时工作要处理,多线程调用:

  1. packageorg.mlinge.s02;
  2. publicclassMyThreadextendsThread{
  3. @Override
  4. publicvoidrun(){
  5. System.out.println(MySingleton.getInstance().hashCode());
  6. }
  7. publicstaticvoidmain(String[]args){
  8. MyThread[]mts=newMyThread[10];
  9. for(inti=0;i<mts.length;i++){
  10. mts[i]=newMyThread();
  11. }
  12. for(intj=0;j<mts.length;j++){
  13. mts[j].start();
  14. }
  15. }
  16. }

执行结果如下:

  1. 1210420568
  2. 1210420568
  3. 1935123450
  4. 1718900954
  5. 1481297610
  6. 1863264879
  7. 369539795
  8. 1210420568
  9. 1210420568
  10. 602269801

从这里执行结果可以看出,单例的线程安全性并没有得到保证,那要怎么解决呢?

3、线程安全的懒汉式单例

要保证线程安全,我们就得需要使用同步锁机制,下面就来看看我们如何一步步的解决 存在线程安全问题的懒汉式单例(错误的单例)。

(1)、 方法中声明synchronized关键字

出现非线程安全问题,是由于多个线程可以同时进入getInstance()方法,那么只需要对该方法进行synchronized的锁同步即可:

  1. packageorg.mlinge.s03;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=null;
  4. privateMySingleton(){}
  5. publicsynchronizedstaticMySingletongetInstance(){
  6. try{
  7. if(instance!=null){//懒汉式
  8. }else{
  9. //创建实例之前可能会有一些准备性的耗时工作
  10. Thread.sleep(300);
  11. instance=newMySingleton();
  12. }
  13. }catch(InterruptedExceptione){
  14. e.printStackTrace();
  15. }
  16. returninstance;
  17. }
  18. }

此时任然使用前面验证多线程下执行情况的MyThread类来进行验证,将其放入到org.mlinge.s03包下运行,执行结果如下:

  1. 1689058373
  2. 1689058373
  3. 1689058373
  4. 1689058373
  5. 1689058373
  6. 1689058373
  7. 1689058373
  8. 1689058373
  9. 1689058373
  10. 1689058373

从执行结果上来看,问题已经解决了,但是这种实现方式的运行效率会很低。同步方法效率低,那我们考虑使用同步代码块来实现:

(2)、 同步代码块实现

  1. packageorg.mlinge.s03;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=null;
  4. privateMySingleton(){}
  5. //publicsynchronizedstaticMySingletongetInstance(){
  6. publicstaticMySingletongetInstance(){
  7. try{
  8. synchronized(MySingleton.class){
  9. if(instance!=null){//懒汉式
  10. }else{
  11. //创建实例之前可能会有一些准备性的耗时工作
  12. Thread.sleep(300);
  13. instance=newMySingleton();
  14. }
  15. }
  16. }catch(InterruptedExceptione){
  17. e.printStackTrace();
  18. }
  19. returninstance;
  20. }
  21. }
这里的实现能够保证多线程并发下的线程安全性,但是这样的实现将全部的代码都被锁上了,同样的效率很低下。

(3)、 针对某些重要的代码来进行单独的同步(可能非线程安全)

针对某些重要的代码进行单独的同步,而不是全部进行同步,可以极大的提高执行效率,我们来看一下:

  1. packageorg.mlinge.s04;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=null;
  4. privateMySingleton(){}
  5. publicstaticMySingletongetInstance(){
  6. try{
  7. if(instance!=null){//懒汉式
  8. }else{
  9. //创建实例之前可能会有一些准备性的耗时工作
  10. Thread.sleep(300);
  11. synchronized(MySingleton.class){
  12. instance=newMySingleton();
  13. }
  14. }
  15. }catch(InterruptedExceptione){
  16. e.printStackTrace();
  17. }
  18. returninstance;
  19. }
  20. }
此时同样使用前面验证多线程下执行情况的MyThread类来进行验证,将其放入到org.mlinge.s04包下运行,执行结果如下:
  1. 1481297610
  2. 397630378
  3. 1863264879
  4. 1210420568
  5. 1935123450
  6. 369539795
  7. 590202901
  8. 1718900954
  9. 1689058373
  10. 602269801
从运行结果来看,这样的方法进行代码块同步,代码的运行效率是能够得到提升,但是却没能保住线程的安全性。看来还得进一步考虑如何解决此问题。

(4)、Double Check Locking双检查锁机制(推荐)

为了达到线程安全,又能提高代码执行效率,我们这里可以采用DCL的双检查锁机制来完成,代码实现如下:

  1. packageorg.mlinge.s05;
  2. publicclassMySingleton{
  3. //使用volatile关键字保其可见性
  4. volatileprivatestaticMySingletoninstance=null;
  5. privateMySingleton(){}
  6. publicstaticMySingletongetInstance(){
  7. try{
  8. if(instance!=null){//懒汉式
  9. }else{
  10. //创建实例之前可能会有一些准备性的耗时工作
  11. Thread.sleep(300);
  12. synchronized(MySingleton.class){
  13. if(instance==null){//二次检查
  14. instance=newMySingleton();
  15. }
  16. }
  17. }
  18. }catch(InterruptedExceptione){
  19. e.printStackTrace();
  20. }
  21. returninstance;
  22. }
  23. }
将前面验证多线程下执行情况的MyThread类放入到org.mlinge.s05包下运行,执行结果如下:
  1. 369539795
  2. 369539795
  3. 369539795
  4. 369539795
  5. 369539795
  6. 369539795
  7. 369539795
  8. 369539795
  9. 369539795
  10. 369539795
从运行结果来看,该中方法保证了多线程并发下的线程安全性。

这里在声明变量时使用了volatile关键字来保证其线程间的可见性;在同步代码块中使用二次检查,以保证其不被重复实例化。集合其二者,这种实现方式既保证了其高效性,也保证了其线程安全性。

4、使用静态内置类实现单例模式

DCL解决了多线程并发下的线程安全问题,其实使用其他方式也可以达到同样的效果,代码实现如下:

  1. packageorg.mlinge.s06;
  2. publicclassMySingleton{
  3. //内部类
  4. privatestaticclassMySingletonHandler{
  5. privatestaticMySingletoninstance=newMySingleton();
  6. }
  7. privateMySingleton(){}
  8. publicstaticMySingletongetInstance(){
  9. returnMySingletonHandler.instance;
  10. }
  11. }
以上代码就是使用静态内置类实现了单例模式,这里将前面验证多线程下执行情况的MyThread类放入到org.mlinge.s06包下运行,执行结果如下:
  1. 1718900954
  2. 1718900954
  3. 1718900954
  4. 1718900954
  5. 1718900954
  6. 1718900954
  7. 1718900954
  8. 1718900954
  9. 1718900954
  10. 1718900954
从运行结果来看,静态内部类实现的单例在多线程并发下单个实例得到了保证。

5、序列化与反序列化的单例模式实现

静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。

代码实现如下:

  1. packageorg.mlinge.s07;
  2. importjava.io.Serializable;
  3. publicclassMySingletonimplementsSerializable{
  4. privatestaticfinallongserialVersionUID=1L;
  5. //内部类
  6. privatestaticclassMySingletonHandler{
  7. privatestaticMySingletoninstance=newMySingleton();
  8. }
  9. privateMySingleton(){}
  10. publicstaticMySingletongetInstance(){
  11. returnMySingletonHandler.instance;
  12. }
  13. }
序列化与反序列化测试代码:

  1. packageorg.mlinge.s07;
  2. importjava.io.File;
  3. importjava.io.FileInputStream;
  4. importjava.io.FileNotFoundException;
  5. importjava.io.FileOutputStream;
  6. importjava.io.IOException;
  7. importjava.io.ObjectInputStream;
  8. importjava.io.ObjectOutputStream;
  9. publicclassSaveAndReadForSingleton{
  10. publicstaticvoidmain(String[]args){
  11. MySingletonsingleton=MySingleton.getInstance();
  12. Filefile=newFile("MySingleton.txt");
  13. try{
  14. FileOutputStreamfos=newFileOutputStream(file);
  15. ObjectOutputStreamoos=newObjectOutputStream(fos);
  16. oos.writeObject(singleton);
  17. fos.close();
  18. oos.close();
  19. System.out.println(singleton.hashCode());
  20. }catch(FileNotFoundExceptione){
  21. e.printStackTrace();
  22. }catch(IOExceptione){
  23. e.printStackTrace();
  24. }
  25. try{
  26. FileInputStreamfis=newFileInputStream(file);
  27. ObjectInputStreamois=newObjectInputStream(fis);
  28. MySingletonrSingleton=(MySingleton)ois.readObject();
  29. fis.close();
  30. ois.close();
  31. System.out.println(rSingleton.hashCode());
  32. }catch(FileNotFoundExceptione){
  33. e.printStackTrace();
  34. }catch(IOExceptione){
  35. e.printStackTrace();
  36. }catch(ClassNotFoundExceptione){
  37. e.printStackTrace();
  38. }
  39. }
  40. }
运行以上代码,得到的结果如下:

  1. 865113938
  2. 1442407170
从结果中我们发现,序列号对象的hashCode和反序列化后得到的对象的hashCode值不一样,说明反序列化后返回的对象是重新实例化的,单例被破坏了。那怎么来解决这一问题呢?

解决办法就是在反序列化的过程中使用readResolve()方法,单例实现的代码如下:

  1. packageorg.mlinge.s07;
  2. importjava.io.ObjectStreamException;
  3. importjava.io.Serializable;
  4. publicclassMySingletonimplementsSerializable{
  5. privatestaticfinallongserialVersionUID=1L;
  6. //内部类
  7. privatestaticclassMySingletonHandler{
  8. privatestaticMySingletoninstance=newMySingleton();
  9. }
  10. privateMySingleton(){}
  11. publicstaticMySingletongetInstance(){
  12. returnMySingletonHandler.instance;
  13. }
  14. //该方法在反序列化时会被调用,该方法不是接口定义的方法,有点儿约定俗成的感觉
  15. protectedObjectreadResolve()throwsObjectStreamException{
  16. System.out.println("调用了readResolve方法!");
  17. returnMySingletonHandler.instance;
  18. }
  19. }
再次运行上面的测试代码,得到的结果如下:

  1. 865113938
  2. 调用了readResolve方法!
  3. 865113938
从运行结果可知,添加readResolve方法后反序列化后得到的实例和序列化前的是同一个实例,单个实例得到了保证。

6、使用static代码块实现单例

静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性的实现单例设计模式。

  1. packageorg.mlinge.s08;
  2. publicclassMySingleton{
  3. privatestaticMySingletoninstance=null;
  4. privateMySingleton(){}
  5. static{
  6. instance=newMySingleton();
  7. }
  8. publicstaticMySingletongetInstance(){
  9. returninstance;
  10. }
  11. }
测试代码如下:

  1. packageorg.mlinge.s08;
  2. publicclassMyThreadextendsThread{
  3. @Override
  4. publicvoidrun(){
  5. for(inti=0;i<5;i++){
  6. System.out.println(MySingleton.getInstance().hashCode());
  7. }
  8. }
  9. publicstaticvoidmain(String[]args){
  10. MyThread[]mts=newMyThread[3];
  11. for(inti=0;i<mts.length;i++){
  12. mts[i]=newMyThread();
  13. }
  14. for(intj=0;j<mts.length;j++){
  15. mts[j].start();
  16. }
  17. }
  18. }
运行结果如下:

  1. 1718900954
  2. 1718900954
  3. 1718900954
  4. 1718900954
  5. 1718900954
  6. 1718900954
  7. 1718900954
  8. 1718900954
  9. 1718900954
  10. 1718900954
  11. 1718900954
  12. 1718900954
  13. 1718900954
  14. 1718900954
  15. 1718900954
从运行结果看,单例的线程安全性得到了保证。

7、使用枚举数据类型实现单例模式

枚举enum和静态代码块的特性相似,在使用枚举时,构造方法会被自动调用,利用这一特性也可以实现单例:

  1. packageorg.mlinge.s09;
  2. publicenumEnumFactory{
  3. singletonFactory;
  4. privateMySingletoninstance;
  5. privateEnumFactory(){//枚举类的构造方法在类加载是被实例化
  6. instance=newMySingleton();
  7. }
  8. publicMySingletongetInstance(){
  9. returninstance;
  10. }
  11. }
  12. classMySingleton{//需要获实现单例的类,比如数据库连接Connection
  13. publicMySingleton(){}
  14. }
测试代码如下:

  1. packageorg.mlinge.s09;
  2. publicclassMyThreadextendsThread{
  3. @Override
  4. publicvoidrun(){
  5. System.out.println(EnumFactory.singletonFactory.getInstance().hashCode());
  6. }
  7. publicstaticvoidmain(String[]args){
  8. MyThread[]mts=newMyThread[10];
  9. for(inti=0;i<mts.length;i++){
  10. mts[i]=newMyThread();
  11. }
  12. for(intj=0;j<mts.length;j++){
  13. mts[j].start();
  14. }
  15. }
  16. }
执行后得到的结果:
  1. 1481297610
  2. 1481297610
  3. 1481297610
  4. 1481297610
  5. 1481297610
  6. 1481297610
  7. 1481297610
  8. 1481297610
  9. 1481297610
  10. 1481297610
运行结果表明单例得到了保证,但是这样写枚举类被完全暴露了,据说违反了“职责单一原则”,那我们来看看怎么进行改造呢。

8、完善使用enum枚举实现单例模式

不暴露枚举类实现细节的封装代码如下:

  1. packageorg.mlinge.s10;
  2. publicclassClassFactory{
  3. privateenumMyEnumSingleton{
  4. singletonFactory;
  5. privateMySingletoninstance;
  6. privateMyEnumSingleton(){//枚举类的构造方法在类加载是被实例化
  7. instance=newMySingleton();
  8. }
  9. publicMySingletongetInstance(){
  10. returninstance;
  11. }
  12. }
  13. publicstaticMySingletongetInstance(){
  14. returnMyEnumSingleton.singletonFactory.getInstance();
  15. }
  16. }
  17. classMySingleton{//需要获实现单例的类,比如数据库连接Connection
  18. publicMySingleton(){}
  19. }
验证单例实现的代码如下:

  1. packageorg.mlinge.s10;
  2. publicclassMyThreadextendsThread{
  3. @Override
  4. publicvoidrun(){
  5. System.out.println(ClassFactory.getInstance().hashCode());
  6. }
  7. publicstaticvoidmain(String[]args){
  8. MyThread[]mts=newMyThread[10];
  9. for(inti=0;i<mts.length;i++){
  10. mts[i]=newMyThread();
  11. }
  12. for(intj=0;j<mts.length;j++){
  13. mts[j].start();
  14. }
  15. }
  16. }
验证结果:

  1. 1935123450
  2. 1935123450
  3. 1935123450
  4. 1935123450
  5. 1935123450
  6. 1935123450
  7. 1935123450
  8. 1935123450
  9. 1935123450
  10. 1935123450
验证结果表明,完善后的单例实现更为合理。

以上就是本文要介绍的所有单例模式的实现,相信认真阅读的读者都已经明白文章开头所引入的那几个问题了,祝大家读得开心:-D!


备注:本文的编写思路和实例源码参照《Java多线程编程核心技术》-(高洪岩)一书中第六章的学习案例撰写。


分享到:
评论

相关推荐

    Java 单例模式线程安全问题

    Java 单例模式线程安全问题详解 Java 单例模式线程安全问题是指在 Java 中实现单例模式时,如何确保线程安全的问题。单例模式是指在整个应用程序生命周期中,只有一个实例存在的设计模式。这种模式可以提高性能,...

    Java中懒汉单例设计模式线程安全测试

    Java中懒汉单例设计模式线程安全测试,单例设计模式的测试

    java单例模式实例

    在Java中,有多种实现单例模式的方法,每种都有其特点和适用场景。接下来,我们将深入探讨这些实现方式。 首先,我们来看**懒汉式(Lazy Initialization)**。这种实现方式是在类被首次请求时才创建单例对象,延迟...

    Java 单例模式.pptx

    - **线程安全问题**:懒汉式单例模式在多线程环境下可能会导致创建多个实例,因此需要采用同步机制保证线程安全,例如使用`synchronized`关键字。 - **静态内部类方式** - **实现**: ```java class Single3 {...

    Java 单例模式 工具类

    Java中的单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供全局访问点。在Java编程中,单例模式常用于控制资源的访问,比如数据库连接池、线程池或者日志对象等。本篇文章将深入探讨如何在Java中...

    深入Java单例模式浅析

    总之,Java单例模式有多种实现方式,每种方式都有其适用场景和优缺点。选择哪种实现方式取决于项目需求,如是否需要延迟加载、是否考虑多线程环境、代码的可读性和维护性等。在实际开发中,应根据具体情况灵活选择。

    线程安全的单例模式

    ### 线程安全的单例模式详解 #### 一、单例模式简介 单例模式(Singleton Pattern)是软件开发中最常用的创建型设计模式之一,它的主要目标是确保一个类只有一个实例,并提供一个全局访问点。单例模式在很多场景下...

    使用Java单例模式实现一个简单的日志记录器.txt

    ### 使用Java单例模式实现一个简单的日志记录器 #### 一、单例模式简介 单例模式是一种常用的软件设计模式,在该模式中,一个类只能创建一个实例,并且提供了一个全局访问点来访问该实例。单例模式的主要优点包括...

    Java 单例模式 懒汉模式

    Java 单例模式 懒汉模式 //懒汉式 多线程中不可以保证是一个对象

    浅议单例模式之线程安全(转)

    以上就是单例模式在Java中的常见实现方式,其中线程安全的实现包括饿汉式、静态代码块、双重检查锁定、静态内部类以及枚举方式。在实际应用中,应根据项目需求选择适合的单例实现方式,考虑到性能和线程安全等因素。...

    Java单例模式设计

    Java单例模式是一种常用的设计模式,它保证一个类只有一个实例,并提供全局访问点。这种模式在需要频繁创建和销毁对象的场景中,或者当对象昂贵时(如数据库连接),能够节省系统资源,提高效率。本篇文章将深入探讨...

    Java单例模式深入理解

    Java单例模式是一种设计模式,它允许在程序中创建唯一一个类实例,通常用于管理共享资源,例如数据库连接、线程池或者配置对象等。单例模式的核心在于限制类的构造函数,确保类只能被初始化一次,从而实现全局唯一的...

    Java单例模式的全面总结

    Java中的单例模式主要分为三种实现方式:懒汉式单例、饿汉式单例和登记式单例。 1. 懒汉式单例(Lazy Initialization) 懒汉式单例的特点是在类被加载时不创建实例,而是在首次调用`getInstance()`方法时才进行实例...

    JAVA单例模式的几种实现方法

    ### JAVA单例模式的几种实现方法 #### 一、饿汉式单例类 饿汉式单例类是在类初始化时就已经完成了实例化的操作。这种实现方式简单且线程安全,因为实例化过程是在编译期间完成的,不会受到多线程的影响。 **代码...

    Java实现多种单例模式

    在Java编程中,单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这种模式在需要频繁创建和销毁对象的场景中尤其有用,因为它可以节省系统资源并确保对象间的协调一致。以下是...

    Java单例模式应用研究.pdf

    ### Java单例模式应用研究 #### 一、单例模式概述 单例模式(Singleton Pattern)作为一种最基本的创建型设计模式,其主要目的是控制一个类的实例化过程,确保在整个应用程序中仅存在一个实例,并且该实例能够被全局...

    java单例模式的例子

    Java单例模式是一种常见的设计模式,它在软件工程中用于控制类的实例化过程,确保一个类只有一个实例,并提供一个全局访问点。这种模式在系统资源管理、缓存、日志记录等方面应用广泛。下面我们将深入探讨Java单例...

    java单例模式连接数据库源码

    Java单例模式是一种设计模式,它保证一个类只有一个实例,并提供一个全局访问点。在数据库连接管理中,使用单例模式能有效控制资源,避免频繁创建和关闭数据库连接导致的性能损失和资源浪费。以下是对Java单例模式...

    java设计模式之单例模式.zip

    在Java中实现单例模式有多种方法: 1. **饿汉式(静态常量)**:在类加载时就完成了初始化,所以没有线程安全问题,但这种实现方式无法实现延迟加载。 ```java public class Singleton { private static final ...

Global site tag (gtag.js) - Google Analytics