立即加载/饿汉模式:
public class MyObject {
//立即加载方式 == 饿汉模式
private static MyObject myObject = new MyObject();
private MyObject() {
}
public static MyObject getInstance() {
return myObject;
}
}
public class MyThread extends Thread{
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
延迟加载/懒汉模式:
public class MyObject {
//延迟加载方式 == 懒汉模式
private static MyObject myObject ;
private MyObject() {
}
public static MyObject getInstance() {
if (myObject != null) {
} else {
myObject = new MyObject();
}
return myObject;
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
public class MyThread extends Thread{
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
立即加载 就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接new实例化;
延迟加载 就是在调用get()方法时才被创建,常见的实现办法就是在get()方法中进行new实例化。
延迟加载 的解决方案:(在多线程中无法保持单例)
(1)声明synchronized
(2)尝试代码同步块
(3)针对某些重要的代码进行单独的同步
public class MyObject {
//延迟加载方式 == 懒汉模式
private static MyObject myObject = new MyObject();
private MyObject() {
}
//设置同步方法效率太低了
//整个方法被上锁
//同步代码块,效率也比较低
//针对某些重要得代码进行单独的同步;
public static MyObject getInstance() {
try {
if (myObject != null) {
} else {
Thread.sleep(3000);
synchronized (MyObject.class) {
myObject = new MyObject();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myObject;
}
}
public class MyThread extends Thread{
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
(4)使用DCL双检查锁机制
public class MyObject {
//延迟加载方式 == 懒汉模式
private static MyObject myObject = new MyObject();
private MyObject() {
}
//使用双检测机制来解决问题,既保证了不需要同步代码的异步执行性,又保证了单例的效果;
public static MyObject getInstance() {
try {
if (myObject != null) {
} else {
Thread.sleep(3000);
synchronized (MyObject.class) {
if (myObject == null) {
myObject = new MyObject();
}
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myObject;
}
}
public class MyThread extends Thread{
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
使用静态内部类实现单例模式:
public class MyObject {
//延迟加载方式 == 懒汉模式
//内部类方式
private static class MyObjectHandler{
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance() {
return MyObjectHandler.myObject;
}
}
public class MyThread extends Thread{
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
序列化与反序列化的单例模式实现:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SaveAndRead {
public static void main(String[] args) {
try {
MyObject myObject = MyObject.getInstance();
FileOutputStream fosRef = new FileOutputStream(new File("myObjectFile.txt"));
ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
oosRef.writeObject(myObject);
oosRef.close();
fosRef.close();
System.out.println(myObject.hashCode());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileInputStream fisRef = new FileInputStream(new File("myObjectFile.txt"));
ObjectInputStream iosRef = new ObjectInputStream(fisRef);
MyObject myObject = (MyObject) iosRef.readObject();
iosRef.close();
fisRef.close();
System.out.println(myObject.hashCode());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
import java.io.ObjectStreamException;
import java.io.Serializable;
public class MyObject implements Serializable{
//序列化与反序列化的单例模式的实现
private static final long serialVersiouUID = 888L;
private static class MyObjectHandler{
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance() {
return MyObjectHandler.myObject;
}
protected Object readResolve() throws ObjectStreamException{
System.out.println("调用了readResolve方法");
return MyObjectHandler.myObject;
}
}
使用static代码块实现单例模式:
public class MyObject {
//使用static代码块实现单例模式
private static MyObject instance = null;
private MyObject() {
}
static {
instance = new MyObject();
}
public static MyObject getInstance() {
return instance;
}
}
public class MyThread extends Thread{
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.getInstance().hashCode());
}
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
使用enum枚举数据类型实现单例模式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class MyObject {
//使用enum枚举数据类型实现单例模式
//将枚举类进行暴露,违反了“职责单一原则”
//完善使用enum枚举数据类型实现单例模式
public enum MyEnumSingleton{
connectionFactory;
private Connection connection;
private MyEnumSingleton() {
try {
System.out.println("调用了MyObject的构造");
String url = "";
String username = "";
String password = "";
String driverName = "";
Class.forName(driverName);
connection = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Connection getConnection() {
return connection;
}
}
public static Connection getConnection() {
return MyEnumSingleton.connectionFactory.getConnection();
}
}
public class MyThread extends Thread{
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.getConnection().hashCode());
}
}
}
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}