1.单例模式(singleton)
?
例如:
?
class Soup1{
private Soup(){}
public static Soup1 makeSoup(){
return new Soup1();
}
?
?这个不是单例模式,这个是对象受限创建,只需要简单的加入一下判断,即可是对象创建控制在需要的范围内,
?例如
?
class Soup1{
private Soup(){}
private static int i;
?
public static Soup1 makeSoup(){
if(i<10){ //这里就使对象创建次数控制在10次以内
return new Soup1();
i++;
}
}
?
}
这个对象受限创建的好处有控制对象,减少资源开销,与滥用等等
?
单例模式
class Soup2{
private Soup2(){}
private static Soup2 ps1=new Soup2();
public static Soup2 access(){
return ps1;
}
}
?
好处:是处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回(garbage collection)。利用资源共享等,具体再详细查,迟点补充
?
?
?
?
?
?
?
注:java的几种单例模式 ?http://blog.sina.com.cn/s/blog_3f9f7e71010139tq.html
?
单例模式应用于一个类只有一个实例的情况,并且为其实例提供一个全局的访问点。
特点:
1.一个类只有一个实例
2.自己创建这个实例
3.整个系统只能用这个实例
应用场景
外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。
内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件。
实现方式
1.饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法)
public?class?Singleton1 {?private?Singleton1() { }?public?static?Singleton1 instance =?newSingleton1();?public?Singleton1 getInstance() {?return?instance; } }
?
2.懒汉式:单例实例在第一次被使用时构建,延迟初始化。
class?Singleton2 {?private?Singleton2() { }?public?static?Singleton2 instance =?null;?publicstatic Singleton2 getInstance() {?if?(instance ==?null) {
//多个线程判断instance都为null时,在执行new操作时多线程会出现重复情况 instance =?new?Singleton2(); }?return?instance; } }
懒汉式在单个线程中没有问题,但在多线程就可能会出现两个或多个Singleton2实例情况,
虽然后面实例化的Singleton2会覆盖前面实例化的Singleton2,但最好避免这样的情况。
改进方式就是加锁synchornized
class?Singleton3 {?private?Singleton3() { }?public?static?Singleton3 instance =?null;?publicstatic?synchronized?Singleton3 getInstance() {?if?(instance ==?null) { instance =?newSingleton3(); }?return?instance; } }优点 资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法 缺点 第一次加载时不够快,多线程使用不必要的同步开销大
3.双重检测
class?Singleton4 {?private?Singleton4() { }?public?static?Singleton4 instance =?null;?publicstatic?Singleton4 getInstance() {?if?(instance ==?null) {?synchronized?(Singleton4.class) {?if(instance ==?null) { instance =?new?Singleton4(); } } }?return?instance; } }
?
4.静态内部类
class?Singleton5 {?private?Singleton5() { }?private?static?class?SingletonHelp {?static?Singleton5 instance =?new?Singleton5(); }?public?static?Singleton5 getInstance() {?returnSingletonHelp.instance; } }
?
总结:一般采用饿汉式(1),若对资源十分在意可以采用静态内部类(4),不建议采用懒汉式及双重检测(2、3)
另外
对于第二种可以采用volatile方式
volatile用更低的代价代替同步
解释:同步的代价主要有覆盖范围决定,如果可以降低同步的覆盖范围,可大幅提升性能。
而volatile覆盖范围是变量级别的,因此同步代价很低。
volatile原理:告诉处理器,不要将其放入工作内存,而是直接在主存操作。因此,当多处理器或多线程在访问该变量时
都将直接操作主存,这在本质上做到了变量共享。
volation优势:
1.更大的程度吞吐量
2.更少的代码实现多线程
3.程序伸缩性好
volatile不足:
1.容易出问题
2.比较难设计
?
?
?
?