189 8069 5689

java代码是单例 Java单例

JAVA单例模式有哪些?

一、懒汉式单例

创新互联是一家集网站建设,潮安企业网站建设,潮安品牌网站建设,网站定制,潮安网站建设报价,网络营销,网络优化,潮安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

在类加载的时候不创建单例实例。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。

public

class

LazySingleton

{

/**

*

私有静态对象,加载时候不做初始化

*/

private

static

LazySingleton

m_intance=null;

/**

*

私有构造方法,避免外部创建实例

*/

private

LazySingleton(){

}

/**

*

静态工厂方法,返回此类的唯一实例.

*

当发现实例没有初始化的时候,才初始化.

*/

synchronized

public

static

LazySingleton

getInstance(){

if(m_intance==null){

m_intance=new

LazySingleton();

}

return

m_intance;

}

}

二、饿汉式单例

在类被加载的时候,唯一实例已经被创建。

public

class

EagerSingleton

{

/**

*

私有的(private)唯一(static

final)实例成员,在类加载的时候就创建好了单例对象

*/

private

static

final

EagerSingleton

m_instance

=

new

EagerSingleton();

/**

*

私有构造方法,避免外部创建实例

*/

private

EagerSingleton()

{

}

/**

*

静态工厂方法,返回此类的唯一实例.

*

@return

EagerSingleton

*/

public

static

EagerSingleton

getInstance()

{

return

m_instance;

}

}

**************************************************************************************

懒汉方式,指全局的单例实例在第一次被使用时构建;

饿汉方式,指全局的单例实例在类装载时构建

**************************************************************************************

三、登记式单例

这个单例实际上维护的是一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从工厂直接返回,对于没有登记的,则先登记,而后返回。

public

class

RegSingleton

{

/**

*

登记薄,用来存放所有登记的实例

*/

private

static

Map

m_registry

=

new

HashMap();

//在类加载的时候添加一个实例到登记薄

static

{

RegSingleton

x

=

new

RegSingleton();

m_registry.put(x.getClass().getName(),

x);

}

/**

*

受保护的默认构造方法

*/

protected

RegSingleton()

{

}

/**

*

静态工厂方法,返回指定登记对象的唯一实例;

*

对于已登记的直接取出返回,对于还未登记的,先登记,然后取出返回

*

@param

name

*

@return

RegSingleton

*/

public

static

RegSingleton

getInstance(String

name)

{

if

(name

==

null)

{

name

=

"RegSingleton";

}

if

(m_registry.get(name)

==

null)

{

try

{

m_registry.put(name,

(RegSingleton)

Class.forName(name).newInstance());

}

catch

(InstantiationException

e)

{

e.printStackTrace();

}

catch

(IllegalAccessException

e)

{

e.printStackTrace();

}

catch

(ClassNotFoundException

e)

{

e.printStackTrace();

}

}

return

m_registry.get(name);

}

/**

*

一个示意性的商业方法

*

@return

String

*/

public

String

about()

{

return

"Hello,I

am

RegSingleton!";

}

}

java中的单例模式的代码怎么写

我从我的博客里把我的文章粘贴过来吧,对于单例模式模式应该有比较清楚的解释:

单例模式在我们日常的项目中十分常见,当我们在项目中需要一个这样的一个对象,这个对象在内存中只能有一个实例,这时我们就需要用到单例。

一般说来,单例模式通常有以下几种:

1.饥汉式单例

public class Singleton {

private Singleton(){};

private static Singleton instance = new Singleton();

public static Singleton getInstance(){

return instance;

}

}

这是最简单的单例,这种单例最常见,也很可靠!它有个唯一的缺点就是无法完成延迟加载——即当系统还没有用到此单例时,单例就会被加载到内存中。

在这里我们可以做个这样的测试:

将上述代码修改为:

public class Singleton {

private Singleton(){

System.out.println("createSingleton");

};

private static Singleton instance = new Singleton();

public static Singleton getInstance(){

return instance;

}

public static void testSingleton(){

System.out.println("CreateString");

}

}

而我们在另外一个测试类中对它进行测试(本例所有测试都通过Junit进行测试)

public class TestSingleton {

@Test

public void test(){

Singleton.testSingleton();

}

}

输出结果:

createSingleton

CreateString

我们可以注意到,在这个单例中,即使我们没有使用单例类,它还是被创建出来了,这当然是我们所不愿意看到的,所以也就有了以下一种单例。

2.懒汉式单例

public class Singleton1 {

private Singleton1(){

System.out.println("createSingleton");

}

private static Singleton1 instance = null;

public static synchronized Singleton1 getInstance(){

return instance==null?new Singleton1():instance;

}

public static void testSingleton(){

System.out.println("CreateString");

}

}

上面的单例获取实例时,是需要加上同步的,如果不加上同步,在多线程的环境中,当线程1完成新建单例操作,而在完成赋值操作之前,线程2就可能判

断instance为空,此时,线程2也将启动新建单例的操作,那么多个就出现了多个实例被新建,也就违反了我们使用单例模式的初衷了。

我们在这里也通过一个测试类,对它进行测试,最后面输出是

CreateString

可以看出,在未使用到单例类时,单例类并不会加载到内存中,只有我们需要使用到他的时候,才会进行实例化。

这种单例解决了单例的延迟加载,但是由于引入了同步的关键字,因此在多线程的环境下,所需的消耗的时间要远远大于第一种单例。我们可以通过一段测试代码来说明这个问题。

public class TestSingleton {

@Test

public void test(){

long beginTime1 = System.currentTimeMillis();

for(int i=0;i100000;i++){

Singleton.getInstance();

}

System.out.println("单例1花费时间:"+(System.currentTimeMillis()-beginTime1));

long beginTime2 = System.currentTimeMillis();

for(int i=0;i100000;i++){

Singleton1.getInstance();

}

System.out.println("单例2花费时间:"+(System.currentTimeMillis()-beginTime2));

}

}

最后输出的是:

单例1花费时间:0

单例2花费时间:10

可以看到,使用第一种单例耗时0ms,第二种单例耗时10ms,性能上存在明显的差异。为了使用延迟加载的功能,而导致单例的性能上存在明显差异,

是不是会得不偿失呢?是否可以找到一种更好的解决的办法呢?既可以解决延迟加载,又不至于性能损耗过多,所以,也就有了第三种单例:

3.内部类托管单例

public class Singleton2 {

private Singleton2(){}

private static class SingletonHolder{

private static Singleton2 instance=new Singleton2();

}

private static Singleton2 getInstance(){

return SingletonHolder.instance;

}

}

在这个单例中,我们通过静态内部类来托管单例,当这个单例被加载时,不会初始化单例类,只有当getInstance方法被调用的时候,才会去加载

SingletonHolder,从而才会去初始化instance。并且,单例的加载是在内部类的加载的时候完成的,所以天生对线程友好,而且也不需要

synchnoized关键字,可以说是兼具了以上的两个优点。

4.总结

一般来说,上述的单例已经基本可以保证在一个系统中只会存在一个实例了,但是,仍然可能会有其他的情况,导致系统生成多个单例,请看以下情况:

public class Singleton3 implements Serializable{

private Singleton3(){}

private static class SingletonHolder{

private static Singleton3 instance = new Singleton3();

}

public static Singleton3 getInstance(){

return SingletonHolder.instance;

}

}

通过一段代码来测试:

@Test

public void test() throws Exception{

Singleton3 s1 = null;

Singleton3 s2 = Singleton3.getInstance();

//1.将实例串行话到文件

FileOutputStream fos = new FileOutputStream("singleton.txt");

ObjectOutputStream oos =new ObjectOutputStream(fos);

oos.writeObject(s2);

oos.flush();

oos.close();

//2.从文件中读取出单例

FileInputStream fis = new FileInputStream("singleton.txt");

ObjectInputStream ois = new ObjectInputStream(fis);

s1 = (Singleton3) ois.readObject();

if(s1==s2){

System.out.println("同一个实例");

}else{

System.out.println("不是同一个实例");

}

}

输出:

不是同一个实例

可以看到当我们把单例反序列化后,生成了多个不同的单例类,此时,我们必须在原来的代码中加入readResolve()函数,来阻止它生成新的单例

public class Singleton3 implements Serializable{

private Singleton3(){}

private static class SingletonHolder{

private static Singleton3 instance = new Singleton3();

}

public static Singleton3 getInstance(){

return SingletonHolder.instance;

}

//阻止生成新的实例

public Object readResolve(){

return SingletonHolder.instance;

}

}

再次测试时,就可以发现他们生成的是同一个实例了。

在java开发中,为什么要使用单例模式?

java单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。

特点:

一个类只能有一个实例;

自己创建这个实例;

整个系统都要使用这个实例。

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。一些资源管理器常常设计成单例模式。

外部资源:譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干个通信端口,系统应当集中管理这些通信端口,以避免一个通信端口被两个请求同时调用。

内部资源,譬如,大多数的软件都有一个(甚至多个)属性文件存放系统配置。这样的系统应当由一个对象来管理这些属性文件。

单例模式,能避免实例重复创建;

单例模式,应用于避免存在多个实例引起程序逻辑错误的场合;

单例模式,较节约内存。

java 单例模式这个要怎么理解?

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

介绍

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁。

何时使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

应用实例:

1、一个班级只有一个班主任。

2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。

3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

优点:

1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景:

1、要求生产唯一序列号。

2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。

3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

在Java中,单例设计模式是什么意思?有什么优势?

单例模式:保证一个类在使用过程中,只有一个实例。

优势就是单例模式的作用,这个类永远只有一个实例。

还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收。

java的学习建议:

首先要看书读理论,不一定都懂,因为有一个懂的过程;

然后就是分析代码,看看书上的代码的意思,逐行逐行地看,去体会;

最重要的一点就是敲写代码,刚开始不会没关系,照着书一行一行的敲,然后运行,观察结果,把程序运行结果联系程序代码,学得多一点了就尝试修改代码,改一点点看运行结果有什么变化,便于理解程序内部执行的机制。


网页名称:java代码是单例 Java单例
转载来于:http://cdxtjz.cn/article/hiehse.html

其他资讯