单例模式与多线程
6.1 立即加载/“饿汉模式”
public class MyObject {
private static MyObject myObject=new MyObject();
private MyObject() {
}
public static MyObject getInstance() {
return myObject;
}
}
public class MyThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
super.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();
}
}
6.2 延迟加载/“懒汉模式”
(1)声明synchronized关键字
public class MyObject {
private volatile static MyObject myObject;
private MyObject() {}
public static MyObject getInstance() {
try {
if(myObject != null) {
}else {
Thread.sleep(3000);
myObject = new MyObject();
}
} catch (Exception e) {
e.printStackTrace();
}
return myObject;
}
}
package com.wz.thread.delay;
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println(MyObject.getInstance().hashCode());
}
}
package com.wz.thread.delay;
/**
* 输出的hascode值相同,说明是同一个对象
* @author Administrator
*
*/
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();
}
}
(2)使用DCL双检查锁机制
public class MyObject {
private volatile static MyObject 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 (Exception e) {
e.printStackTrace();
}
return myObject;
}
}
package com.wz.thread.delay;
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println(MyObject.getInstance().hashCode());
}
}
package com.wz.thread.delay;
/**
* 输出的hascode值相同,说明是同一个对象
* @author Administrator
*
*/
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();
}
}
6.3 使用静态内置类实现单例模式
静态代码块和静态内部类的加载顺序:当调用外部类的构造函数是,外部类的静态代码块同时被加载,但是其内部类不会同时被加载;当且仅当内部类的静态域或其构造方法或其静态方法被调用时,内部内才被加载。
public class MyObject implements Serializable{
private static class MyObjectHandle {
private static MyObject myObject = new MyObject();
}
private MyObject(){
}
public static MyObject getInstance() {
return MyObjectHandle.myObject;
}
}
在序列化和反序列化的过程中会出现问题。
6.4 序列化和反序列化的单例模式实现
public class SingleTest implements Serializable{
private static final long serialVersionUID = -8600246627673134435L;
private static class SingleTestHandler{
private static SingleTest singleTest=new SingleTest();
}
private SingleTest() {
}
public static SingleTest getInstance(){
return SingleTestHandler.singleTest;
}
protected Object readResolve() throws ObjectStreamException{
System.out.println("调用了readResolve方法!");
return SingleTestHandler.singleTest;
}
}
class MyThead extends Thread{
public void run(){
System.out.println(SingleTest.getInstance().hashCode());
}
}
class Test1{
public static void main(String[] args) {
try {
SingleTest singleTest=SingleTest.getInstance();
FileOutputStream fileOutputStream=new FileOutputStream(new File("myObjectFilee.txt"));
ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(singleTest);
objectOutputStream.close();
fileOutputStream.close();
System.out.println(singleTest.hashCode());
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fileInputStream=new FileInputStream(new File("myObjectFilee.txt"));
ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);
SingleTest singleTest=(SingleTest) objectInputStream.readObject();
objectInputStream.close();
fileInputStream.close();
System.out.println(singleTest.hashCode());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
6.5 使用static代码块实现单例模式
package com.wz.thread.staticlump;
public class MyObject {
private static MyObject instance = null;
private MyObject() {}
static {
instance = new MyObject();
}
public static MyObject getInstance() {
return instance;
}
}
package com.wz.thread.staticlump;
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.getInstance().hashCode());
}
}
}
package com.wz.thread.staticlump;
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();
}
}
6.6 使用enum枚举数据类型实现单例模式
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class MyObject {
public enum MyEnumSingleton{
connectionFactory;
private Connection connection;
private MyEnumSingleton() {
try {
System.out.println("调用了MyObject构造");
String url = "jdbc:sqlserver://localhost:1079;databaseName=ghydb";
String username = "sa";
String password = "";
String driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
Class.forName(driverClass);
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 MyEnumSingleton.connectionFactory.getConnection();
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.getConnection().hashCode());
}
}
}