您的位置:首页 > 其它

单例模式与多线程

2017-08-27 22:22 169 查看
  单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

  1.)某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

  2.)省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

  3.)有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程

  

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

public class Singleton {
private Singleton(){
}

private static final Singleton singleton = new Singleton();

public static Singleton getInstance() {
return singleton;
}
}


public class Singleton {
/* 私有构造方法,防止被实例化 */
private Singleton() {
}

/* 此处使用一个内部类来维护单例 */
private static class SingletonFactory {
private static Singleton instance = new Singleton();
}

/* 获取实例 */
public static Singleton getInstance() {
return SingletonFactory.instance;
}

/* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
public Object readResolve() {
return getInstance();
}
}


自定义线程

public class MyThread extends Thread {
@Override
public void run() {
System.out.println(Singleton.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) throws ParseException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}


1756075494

1756075494

1756075494

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

  静态内置类可以达到线程安全问题,但如果遇到序列化对象时,使用默认的方式运行得到的结果还是多例的。

public class Singleton implements Serializable{
/* 私有构造方法,防止被实例化 */
private Singleton() {
}

/* 此处使用一个内部类来维护单例 */
private static class SingletonFactory {
private static Singleton instance = new Singleton();
}

/* 获取实例 */
public static Singleton getInstance() {
return SingletonFactory.instance;
}

/* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
protected Object readResolve() throws ObjectStreamException{
System.out.println("调用了readResolve方法");
return getInstance();
}
}


创建业务类SaveAndRead,代码如下:

public class SaveAndRead {
public static void main(String[] args)  {
try {
Singleton singleton = Singleton.getInstance();
FileOutputStream fosRef = new FileOutputStream(new File("mySingletonFIle.txt"));
ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
oosRef.writeObject(singleton);

oosRef.close();
fosRef.close();
System.out.println(singleton.hashCode());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

try{
FileInputStream fisRef = new FileInputStream(new File("mySingletonFIle.txt"));
ObjectInputStream iosRef = new ObjectInputStream(fisRef);
Singleton singleton = (Singleton) iosRef.readObject();
iosRef.close();
fisRef.close();
System.out.println(singleton.hashCode());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}


723635264

调用了readResolve方法

723635264

如果把Singleton类里的readResolve方法注释掉,则结果会是这样的

1484511730

588729095

不是同一个对象

3、使用static代码块实现单例模式

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

public class Singleton {
/* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;

/* 私有构造方法,防止被实例化 */
private Singleton() {
}

static {
instance = new Singleton();
}

public static Singleton getInstance() {
return instance;
}
}


自定义线程MyThread和Run类不变,结果如下:

1032010069

1032010069

1032010069

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

  枚举enum和静态代码块的特性相似,在使用枚举类时,构造方法会被自动调用,也可以应用其这个特性实现单例设计模式,最经典的就是数据库连接。

public class Singleton {
// 枚举类要放单例里防止暴露,不然就违反了“职责单一原则”
public enum MySingleton {
connectionFactory;
private Connection connection;

private MySingleton() {
try {
System.out.print("调用了Singleton的构造!");
String url = "jdbc:sqlserver://localhost:1079;databaseNme=DB";
String username = "123456";
String password = "123456";
String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
Class.forName(driverName);
connection = DriverManager.getConnection(url, username,password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}

public Connection getConnection() {
return connection;
}
}

public static Connection getConnection() {
return MySingleton.connectionFactory.getConnection();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Singleton 多线程