众所周知线程安全就等于效率会相对低点。所有经过改造优化,出现另一种双重判断方式。代码如下:
/*** 加锁后的,单例模式类 +优化后
*@authorwanghao
**/
classSinglePattern{private staticSinglePattern instance ;//1.构造方法私有化
privateSinglePattern() {
}//2.提供一个全局访问点 加锁后
public staticSinglePattern getInstance() {if(instance == null) {synchronized(SinglePattern.class) {if(instance == null) {
instance= newSinglePattern();
}
}
}returninstance;
}
}
单例模式重点就一个对象,这样理论上会是创建次数少获取的次数多。所以,我们只需加锁创建对象的方式,而判断是否为null,可以不加锁。可以提高效率。
如果按前面一种方式,如果高并发10个线程同时访问,则需要耗费10*(等待时间+判断时间),
而如果用第二张方式,如果通用10个线程访问,则只需10*(判断时间),如果没有对象则再加上一次判断时间和创建对象的时间。
有的人会问,上面只是为了优化, 需要两个if判断。我们先用一个判断人后只需上面的代码,验证结果后在说原因吧。为去掉锁里面的判断执行结果为:
两个实例,这是为什么呢?
这是因为刚开始instance实例肯定是null的,T1和T2线程里面都是空实例,所以都过了if判断,然后到达锁门口,T2跑的快拿到锁了,进去创建了个对象出去了。(注:这时候已经有对象了)然后因为T1线程已经通过判断,到达创建对象锁门口,等T1归还了锁之后,T1线程进入创建对象。然后出去。这时候两个线程就创建了两个对象。
所以才要在锁里面判断对象是否为空。
工厂模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
把对象比作产品,创建对象的地方叫做工厂,如:Spring中的Bean和容器。
简单工厂模式 ,代码实现:
一个抽象类水,和三个子类,农夫三拳,哇哈哈,百岁山类。
/*** 我家卖水的
*@authorwanghao
**/
abstract classWater{//卖的是可以喝的水
public abstract voiddrink();
}//农夫三拳 水
class NongFuWater extendsWater{
@Overridepublic voiddrink() {
System.out.println("农夫三拳有点甜。");
}
}//哇哈哈 水
class WaHaWater extendsWater{
@Overridepublic voiddrink() {
System.out.println("哇哈哈也有点甜。");
}
}//百岁山 水
class BaiSuiWater extendsWater{
@Overridepublic voiddrink() {
System.out.println("百岁山也是甜的。");
}
}
然后创建个工厂存放我的水。进行销售:
classWaterFactory{public staticWater getWater(String waterName) {
Water water= null;switch(waterName) {case "农夫三拳":
water= newNongFuWater();break;case "哇哈哈":
water= newWaHaWater();break;case "百岁山":
water= newBaiSuiWater();break;
}returnwater;
}
}
然后写测试类:
public static voidmain(String[] args) {//等待顾客买水
Water water = null;
System.out.println("来个农夫三拳");//去我工厂拿水
water = WaterFactory.getWater("农夫三拳");
water.drink();
System.out.println("还渴,再来瓶哇哈哈");//去我工厂拿水
water = WaterFactory.getWater("哇哈哈");
water.drink();
System.out.println("还渴,再来瓶百岁山");//去我工厂拿水
water = WaterFactory.getWater("百岁山");
water.drink();
System.out.println("还渴,再来瓶洛阳宫");//去我工厂拿水
water = WaterFactory.getWater("洛阳宫");if(water == null) {
System.out.println("没有该水。");
}
}
运行结果为:
这就是简单的工厂模式。也叫静态工厂。
利用反射创建工厂对象
还有上面的例子只是把工厂换做基于反射的例子:代码如下:
classReflexFactory {public static T getWater(Classclz) {
T t= null;try{
t=(T) Class.forName(clz.getName()).newInstance();
}catch(Exception e) {
e.printStackTrace();
}returnt;
}
}
然后把Demo的工厂换做反射工厂。代码如下:只写了一个,后面略。
运行结果为:
看了网上之后有多种创建工厂的方法下面只列出代码:
多方法工厂模式,需要什么调什么
//多方法工厂模式,需要什么就调什么
classWaterFactory{public staticNongFuWater getNongFuWater() {return newNongFuWater();
}public staticWaHaWater getWaHaWater() {return newWaHaWater();
}public staticBaiSuiWater getBaiSuiWater() {return newBaiSuiWater();
}
}
还有java源码的工厂模式:例如线程池都知道创建线程池子的方法有很多,其中有一种为创建固定数量的线程池方法:
/**创建具一个可重用的,有固定数量的线程池
* 每次提交一个任务就提交一个线程,直到线程达到线城池大小,就不会创建新线程了
* 线程池的大小达到最大后达到稳定不变,如果一个线程异常终止,则会创建新的线程*/ExecutorService es=Executors.newFixedThreadPool(2);for(int i=0;i<10;i++){
ThreadChi tc=newThreadChi();
es.execute(tc);
}
es.shutdown();