单例设计模式:保证类在内存中只有一个对象。
如何保证类在内存中只有一个对象?
(1)控制类的创建,不让其他类来创建本类的对象。private
(2)在本类中定义一个本类的对象。
(3)提供公共的访问方式,例如:
public static MyObject getInstance() {
return myObject;
}
单例写法两种:
(1)饿汉模式。
(2)懒汉模式。
立即加载/“饿汉模式”
什么是立即加载?立即加载就是使用类的时候已经将对象创建完毕,常见的实现办法就是直接new实例化。而立即加载从中文的语境来看,有,“着急”、“急迫”的含义,所以称为“饿汉模式”。
package unit6;
public class Demo1_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();
}
}
class MyThread extends Thread {
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
class MyObject {
//立即加载方式==饿汉模式
private static MyObject myObject = new MyObject();
private MyObject() {
}
public static MyObject getInstance() {
//此代码版本为立即加载
//此版本代码的缺点是不能有其他势力变量
//因为getInstance()方法没有同步
//所以有可能出现非线程安全问题
return myObject;
}
}
延迟加载/“懒汉模式”
什么是延迟加载?延迟加载就是在调用get()方法时实例才被创建,常见的实例办法就是在get()方法中进行new实例化。而延迟加载从中文的语境来看,是“缓慢”、“不急迫”的含义,所以也称为“懒汉模式”。
package unit6;
public class Demo2_Run {
public static void main(String[] args) {
Demo2_MyThread t1 = new Demo2_MyThread();
t1.start();
}
}
class Demo2_MyThread extends Thread {
public void run() {
int integer = Demo2_MyObject.getInstance().hashCode();
System.out.println(integer);
}
}
class Demo2_MyObject {
private static Demo2_MyObject myObject;
private Demo2_MyObject() {
}
public static Demo2_MyObject getInstance() {
//延迟加载
if (myObject != null) {
} else {
myObject = new Demo2_MyObject();
}
return myObject;
}
}
延迟加载/“懒汉模式”的缺点
在多线程的环境中,就会出现取出多个实例的情况,与单例模式的初衷是相背离的。
package unit6;
public class Demo2_Run {
public static void main(String[] args) {
Demo2_MyThread t1 = new Demo2_MyThread();
Demo2_MyThread t2 = new Demo2_MyThread();
t1.start();
t2.start();
}
}
class Demo2_MyThread extends Thread {
public void run() {
int integer = Demo2_MyObject.getInstance().hashCode();
System.out.println(integer);
}
}
class Demo2_MyObject {
private static Demo2_MyObject myObject;
private Demo2_MyObject() {
}
public static Demo2_MyObject getInstance() {
//延迟加载
if (myObject != null) {
} else {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myObject = new Demo2_MyObject();
}
return myObject;
}
}
使用静态内置类实现单例模式
package unit6;
public class Demo3_Run {
public static void main(String[] args) {
Demo3_MyThread t1 = new Demo3_MyThread();
Demo3_MyThread t2 = new Demo3_MyThread();
Demo3_MyThread t3 = new Demo3_MyThread();
t1.start();
t2.start();
t3.start();
}
}
class Demo3_MyThread extends Thread {
public void run() {
System.out.println(Demo3_MyObject.getInstance().hashCode());
}
}
class Demo3_MyObject {
//内部类
private static class MyObjectHandler {
private static Demo3_MyObject myObject = new Demo3_MyObject();
}
private Demo3_MyObject() {
}
public static Demo3_MyObject getInstance() {
return MyObjectHandler.myObject;
}
}
使用static代码块实现单例模式
静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性来实现单例设计模式。
package unit6;
public class Demo4_Run {
public static void main(String[] args) {
Demo4_MyThread t1 = new Demo4_MyThread();
Demo4_MyThread t2 = new Demo4_MyThread();
Demo4_MyThread t3 = new Demo4_MyThread();
t1.start();
t2.start();
t3.start();
}
}
class Demo4_MyThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Demo4_MyObject.getInstance().hashCode());
}
}
}
class Demo4_MyObject {
private static Demo4_MyObject instance = null;
private Demo4_MyObject() {
}
static {
instance = new Demo4_MyObject();
}
public static Demo4_MyObject getInstance() {
return instance;
}
}