码迷,mamicode.com
首页 > 编程语言 > 详细

浅析java单例模式

时间:2016-10-18 02:03:08      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:

单例模式:运行期间有且仅有一个实例

一. 关键点:

1.一个类只有一个实例------最基本的-----(只提供私有构造器)

2.该类必须自行创建这个实例-----(定义了静态的该类的私有对象)

3.该类必须自行向整个系统提供这个实例---(提供一个静态的公有方法,返回创建或者获取本身的静    态私有对象)

二.基本单例模式

1.懒汉模式

懒汉模式:在类加载的时候,不创建实例,运行调用的时候创建(以时间换空间

   优缺点:类加载快,在运行时获取速度慢;线程不安全;

解决懒汉模式线程安全方法:(1)方法体加同步(2)双重校验锁

懒汉模式特性:lazy  Loading(延迟加载)    

2.饿汉模式

饿汉模式:在类加载的时候就会完成初始化。(以空间换时间

优缺点:类加载慢,但在运行时获取对象速度快;线程安全

 三.代码展示  

懒汉模式代码:

import java.io.IOException;

import java.io.InputStream;

import java.util.Properties;

 

/**

 * 读取数据库配置文件的工具类--单例模式

 * */

public class ConfigManager {

// 01定义静态私有本类对象

private static ConfigManager configManager;

private static Properties properties;

// 02私有化本类构造方法--读取配置文件

private ConfigManager() {

// 定义要读取的配置文件

String configFile = "database.properties";

properties = new Properties();

// 以输入流的形式获取配置文件

/**

 * ConfigManager.class.getClassLoader():获取本类根目录

 * getResourceAsStream(configFile):以流的形式获取配置文件

 * */

InputStream is = ConfigManager.class.getClassLoader()

.getResourceAsStream(configFile);

try {

// 读取配置文件(把流放入properties对象)

properties.load(is);

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

// 关闭流

is.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

//03 提供全局访问接口

/**

 * 懒汉模式:线程不安全,在多线程并发情况下,

 * 可能会创建多个ConfigManager实例

 *

 *

 * 001简单懒汉模式--适合单线程安全

 * public static ConfigManager getInstance() {

if (configManager == null) {

configManager = new ConfigManager();

}

return configManager;

}

 

 * 解决线程安全问题:

 //002.方法体加同步,每一个时间点只允许一个线程通过该方法

public static  synchronized ConfigManager getInstance() {

if (configManager == null) {

configManager = new ConfigManager();

}

return configManager;

}

// 04获得properties对象的值

public String getString (String key) {

return properties.getProperty(key);

}

 

       饿汉模式代码

 1 import java.io.IOException;
 2 import java.io.InputStream;
 3 import java.util.Properties;
 4 
 5 /**
 6  * 读取数据库配置文件的工具类--单例模式
 7  * */
 8 public class ConfigManager {
 9     // 01定义静态私有本类对象
10        private static ConfigManager configManager=new ConfigManager();//初始化实例
          private static Properties properties;
15     // 02私有化本类构造方法--读取配置文件
16     private ConfigManager() {  
17         // 定义要读取的配置文件
18         String configFile = "database.properties";
19         properties = new Properties();
20         // 以输入流的形式获取配置文件
21         /**
22          * ConfigManager.class.getClassLoader():获取本类根目录
23          * getResourceAsStream(configFile):以流的形式获取配置文件
24          * */
25         InputStream is = ConfigManager.class.getClassLoader()
26                 .getResourceAsStream(configFile);
27         try {
28             // 读取配置文件(把流放入properties对象)
29             properties.load(is);
30         } catch (IOException e) {
31             e.printStackTrace();
32         } finally {
33             try {
34                 // 关闭流
35                 is.close();
36             } catch (IOException e) {
37                 e.printStackTrace();
38             }
39         }
40     }
41     //03 提供全局访问接口
42     
69 /*饿汉模式
70  * 线程安全:在加载类时创建实例,因为实例是static,
71  *所以只加载一次
72  * */
73     
74     public static   ConfigManager getInstance(){
75         return  configManager;
76     }
77 
78 
79     // 04获得properties对象的值
80     public String getString (String key) {
81         return properties.getProperty(key);
82     }
83 }

*********************注解*********************

/**

 * 单例模式讲解类 讲解各种单例模式用法

 *

 * */

      public class SingleTon {

 // 饿汉模式变种:静态代码块

      private static SingleTon singleTon = null;

       static {

 //类加载是执行静态代码块,只执行一次

       singleTon = new SingleTon();

      }

private SingleTon() { }

   public static SingleTon getInstance() {

         return singleTon;

}

   }

 

**************************************************

// 懒汉模式线程安全之双重校验锁

private static SingleTon singleTon;

 

private SingleTon() {

}

 

public static SingleTon getInstance() {

          if (singleTon == null) {//第一重校验(第一批并发线程以后的线程不会通过这里,因为已经实例化)

                  synchronized (SingleTon.class) {//锁,类同步安全(只允许一批并发线程中的一个线程通过)

                         if (singleTon == null) {//第二重校验(非空判断,实例为空通过,不为空止步)

                                      singleTon = new SingleTon();//校验全部通过,创建实例

                      }

              }

       }

                 return singleTon;

         }

}

 

测试模拟多线程并发与双重锁

package cn.bdqn.util;

/**

 * 线程类

 * 模拟多线程并发

 * */

public class ThreadDemo extends Thread {

private String threadNo;

public ThreadDemo() {

}

public ThreadDemo(String threadNo) {

this.threadNo = threadNo;

}

public String getThreadNo() {

return threadNo;

}

public void setThreadNo(String threadNo) {

this.threadNo = threadNo;

}

 

@Override

public void run() {

       super.run();

//调用单利模式方法,模拟测试双重锁

       System.out.println(threadNo);

       SingleTon.getInstance(threadNo);

     }

}

 

package cn.bdqn.util;

/*

 * 测试类,测试线程双重锁

 *

 * */

public class ThreadTest {

 

public static void main(String[] args) {

for (int i = 0; i < 7; i++) {// 相当于主线程,获取资源之后,瞬间生成n个子线程,相当于并发

              new ThreadDemo("线程" + i).start();// 创建子线程,并开启

               if (i == 3) {

                  try {

                         Thread.sleep(1000);//模拟多批线程先后并发

                         System.out.println("sleep*********");

                       } catch (InterruptedException e) {

                                e.printStackTrace();

                }

            }

       }

执行结果:

技术分享

   *****************************************************

/**

 * 静态内部类:解决饿汉模式实现lazy loading(延迟加载)

 *

 * */

//创建静态变量

private static SingleTon singleTon;

//私有构造

private SingleTon(){}

//静态内部类

private static class SingleTonHelp{

 //创建静态常量,完成实例化

private static final SingleTon INSTANCE=new SingleTon();

}

   //提供全局访问的接口

public static SingleTon  getInstance(){

return SingleTonHelp.INSTANCE;

}

  //测试方法

public static void test(){

System.out.println("test==============="+singleTon.toString());

}

 

 

package cn.bdqn.util;

/**

 * 测试静态内部类

 *

 * */

public class Test02 {

public static void main(String[] args) {

System.out.println("SingleTon.getInstance()======="+SingleTon.getInstance().toString());

//此时test()报空指针异常,因为没有调用静态类方法,没有加载实例,达到延迟加载效果(即在需要时加载创建实例,不会加载类时加载实例)

    SingleTon.test();

}

}

*****************************************************

什么时候使用单利模式:在比较耗系统性能的时候,比如i/o操作,读取配置文件

懒汉模式特性:lazy  Loading(延迟加载)

懒汉模式:以时间换空间

饿汉模式:以空间换时间(标准饿汉模式为常用模式,不存在线程安全问题)

 

 

浅析java单例模式

标签:

原文地址:http://www.cnblogs.com/liu-chao-feng/p/5971592.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!