单例模式:
- 饿汉式
- 懒汉式
单例模式属于 设计模式的 创建型模式
1.普通实例类:
class Apple{
public void Apple(){
system.out.printf("This is apple instance");
}
public void eat(){
system.out.printf("Apple eat");
}
}
class Test {
public void main(string args[]){
Apple apple=new apple();
apple.eat();
}
}
单例模式:
2 . 饿汉式
class Apple{
private static apple=new Apple();
private Apple(){};
public void eat(){
system.out.printf("apple eat");
}
public static Apple getInstance(){
return apple;
}
}
class Test{
public void main(string args[]){
Apple apple=Apple.getInstance();
apple.eat();
}
}
3.懒汉式
class Apple {
private static Apple apple=null;
private Apple(){};
public void eat(){
system.out.printf("apple eat");
}
public static Apple getInstance(){
if(apple ==null){
apple=new Apple();
}
return apple;
}
}
class Test{
public void main(string args[]){
Apple apple=Apple.getInstance();
apple.eat();
}
}
以上是 理解单例模式的简单例子。 1 普通实例类 2 饿汉式 3 懒汉式
一下简称 1 2 3
2 实例化类使用的是 静态变量。 是类共享的。 但是 2 3 也是有区别的 2 是线程安全的
但是3 呢? 难道就没有用了吗? 并不是, 我们在实际使用时候,有时要在类实例化的时候,进行一些操作, 显然2 是很难实现的 3 就能很好的实现。
1 和 2 3 的区别 2,3 中类的构造方法是私有的也就意味着, 2 3 是没有 像 1 中那样 new 实例的。
现在让我们来看看 如何使 3 线程安全
4.1 懒汉式线程安全 1.0v
class Apple{
private static Apple apple=null;
private Apple(){};
public void eat(){
system.out.printf("apple eat");
}
public static Apple getInstance(){
if(apple ==null){
synchronized(Apple.class){
apple=new Apple();
}
}
return apple;
}
}
//以下的测试和这个test一样,不再进行测试代码的
class Test{
public void main(string args[]){
Apple apple=Apple.getInstance();
apple.eat();
}
}
4.1 只会使 要实例的代码 变成 排队等待 new ,这么和我们的初衷是有出入的。 但是这个 和3 相比已经有进步,考虑到了 线程安全问题, 这不就是 软件 升级迭代的过程吗?也就像我们的成长,每次回首过去,不禁羞愧可笑,但这不就证明这我们的成长吗? 没有开始就十全十美只有在不停的使用中,进行升级迭代。 前提 每个版本都可用啊。
4.2 懒汉式 线程安全 4.2v
class Apple{
private static Apple apple=null;
private Apple(){};
public static Apple getInstance(){
synchronized(Apple.class){
if(apple ==null){
synchronized(Apple.class){
apple=new Apple();
}
}
}
return apple;
}
}
4.2 这样就可以防止 4.1的问题了。 江湖称这种做法叫 双重检查 double-check.
但是jvm 会对 我们的代码进行 指令排序优化。 会破坏我们想做的。
4.3 懒汉式线程安全 4.3v
class Apple{
private volatile static Apple=null;
private Apple(){};
public void eat(){
system.out.printf("apple eat");
}
public static Apple getInstance(){
synchronized(Apple.class){
if(apple ==null){
synchronized(Apple.class){
apple=new Apple();
}
}
}
}
}
volatile 会禁止 jvm 进行 指令排序优化 但是 volatile 是jdk1.5之后实现的,也就是意味这 是依赖jdk 。 不是普世的。
懒汉式2看起来 太过麻烦,既然 饿汉式2是线程安全的,那我们能否使 饿汉式2 在实例之前做一些事情呢? 答案是可以的。
5.1 饿汉式 简化的实现方式
class Apple{
private static class AppleBuild{
private static Apple apple=new Apple();
}
private Apple (){};
public void eat(){
system.out.printf("apple eat");
}
public static Apple getInstance(){
return AppleBuild.apple;
}
}
5.1 和 4.3 实现的功能是相同的,而且更加简化并且不依赖jdk.
参考:
http://www.10tiao.com/html/151/201702/2665513512/1.html 推荐新手可以关注下这个公众号,写的很有趣味。
http://coolshell.cn/articles/265.html
http://www.javatpoint.com/singleton-design-pattern-in-java