单例模式
2015-07-13 16:23
260 查看
我们在写程序的时候,大部分时候,会把类定义成为public类型的,那么任何类都可以随意的创建该类的对象。但是有时候,这种做法并没有任何意义,频繁的创建对象和回收对象造成内存损耗,所以就有了单例模式
一个类只能创建一个对象,则这个类被成为单例类,这种模式被成为单例模式
单例模式的原则是:
1.把类的构造方法隐藏起来
2.创建一个方法,这个方法可以创建一个(并且只有一个)自己的实例
3.这个方法可以被外部使用
单例模式分为:懒汉模式、饿汉模式和等级模式
懒汉模式:
饿汉模式:
登记模式:
为了避免懒汉式的线程安全问题,我们需要给他加上代码同步
当线程进来判断出single为null时,遇到问题挂起,其余的线程则无法进来,这样就保证了线程的安全
一个类只能创建一个对象,则这个类被成为单例类,这种模式被成为单例模式
单例模式的原则是:
1.把类的构造方法隐藏起来
2.创建一个方法,这个方法可以创建一个(并且只有一个)自己的实例
3.这个方法可以被外部使用
单例模式分为:懒汉模式、饿汉模式和等级模式
懒汉模式:
/**
*懒汉模式,特征是待到使用时,才创建该类对象
*/
publicclassSingle{
//定义一个类变量,来存储该类对象
privatestaticSinglesingle;
//隐藏构造器
privateSingle(){
}
//定义一个方法供外部调用,返回一个该类唯一的对象
publicstaticSinglegetSingle(){
if(single==null){
single=newSingle();
}
returnsingle;
}
publicstaticvoidmain(String[]args){
Singles1=Single.getSingle();
Singles2=Single.getSingle();
if(s1==s2){
System.out.println("Single类是单例模式");
}else{
System.out.println("Single类不是单例模式");
}
}
}
饿汉模式:
/**
*饿汉模式饿汉模式特征是在类加载时候已经创建好实例待调用,并且该实例不可变
*/
publicclassSingle{
//直接创建该类的实例,该实例不可变
privatestaticfinalSinglesingle=newSingle();
//隐藏构造函数
privateSingle(){
}
//创建一个方法供外部调用,返回该类的实例
publicstaticSinglegetSingle(){
returnsingle;
}
publicstaticvoidmain(String[]args){
Singles1=Single.getSingle();
Singles2=Single.getSingle();
if(s1==s2){
System.out.println("Single类是单例模式");
}else{
System.out.println("Single类不是单例模式");
}
}
}
登记模式:
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Set;
/**
*单例模式之登记模式,特征是事先维护一组map存放一个实例,当创建实例时,先查看map是否存在,如果存在,则直接返回,如果不存在,则先存入,再返回
*/
publicclassSingle{
//定义一个map,用来登记实例
privatestaticMap<String,Single>map=newHashMap<String,Single>();
//先在map中存放一个Single实例
static{
Singlesingle=newSingle();
map.put(single.getClass().getName(),single);
}
//隐藏构造器
privateSingle(){
}
//定义一个方法供外部调用,用来返回实例,需要传入一个参数作为map中的“键”
publicstaticSinglegetSingle(Stringkey){
//如果传入的参数为null,则讲类名称赋值给它
if(key==null){
key=Single.class.getName();
}
//根据传入的“键”判断是否存在“值”,如果不存在,则将该
if(map.get(key)==null){
try{
map.put(key,(Single)Class.forName(key).newInstance());
}catch(InstantiationExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(IllegalAccessExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
returnmap.get(key);
}
publicstaticvoidmain(String[]args){
Singlesingle1=Single.getSingle(null);
Singlesingle2=Single.getSingle(null);
System.out.println(single1==single2);
}
}
单例中的线程安全问题
饿汉式这种一开始就创建实例的方式,线程是安全的,懒汉式则不同,看代码publicclassSingle{
//定义一个类变量,来存储该类对象
privatestaticSinglesingle;
//隐藏构造器
privateSingle(){
}
//定义一个方法供外部调用,返回一个该类唯一的对象
publicstaticSinglegetSingle(){
if(single==null){//当线程执行到这里挂起时,别的线程获取执行权限执行到这里,还会继续给single创建实例,这样就造成了线程安全问题。
single=newSingle();
}
returnsingle;
}
publicstaticvoidmain(String[]args){
Singles1=Single.getSingle();
Singles2=Single.getSingle();
if(s1==s2){
System.out.println("Single类是单例模式");
}else{
System.out.println("Single类不是单例模式");
}
}
}
为了避免懒汉式的线程安全问题,我们需要给他加上代码同步
publicclassThreadForSingle{
publicstaticvoidmain(String[]args){
}
}
classSingle{
privateSingle(){
}
privatestaticSinglesingle=null;
publicstaticSinglegetSingle(){
synchronized(Single.class){
if(single==null){
single=newSingle();
}
}
returnsingle;
}
}
当线程进来判断出single为null时,遇到问题挂起,其余的线程则无法进来,这样就保证了线程的安全
相关文章推荐
- JAVA笔记整理(二),下载安装JDK
- sqlserver权限体系(下)
- Pinyin4j使用手册,HanyuPinyinVCharType的意义
- GRE写作必备句型
- 算法八:Bellman-Ford算法及优化
- Android存储方式的选择
- asm下重定向数据文件小例(使用toad工具)
- 老毛桃装系统详解
- 苹果公司的回复
- Hadoop单机模式安装
- HBase单机环境搭建
- HBase hbase-site.xml 参数
- Hadoop伪分布式模式安装
- JAVA笔记整理(一),JAVA介绍
- 《大型网站系统架构的演化》
- 安装wget1.16
- caffe在windows编译工程及运行mnist数据集测试
- 将UIButton的SEL转成block
- sharepoint获取server端绝对路径的方法
- 静态库 动态库