本文目录一览:
什么是Java单例模式啊?
楼主您好
java模式之单例模式:
单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。
特点:
1,一个类只能有一个实例
2,自己创建这个实例
3,整个系统都要使用这个实例
例: 在下面的对象图中,有一个"单例对象",而"客户甲"、"客户乙" 和"客户丙"是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。一些资源管理器常常设计成单例模式。
外部资源:譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干个通信端口,系统应当集中管理这些通信端口,以避免一个通信端口被两个请求同时调用。内部资源,譬如,大多数的软件都有一个(甚至多个)属性文件存放系统配置。这样的系统应当由一个对象来管理这些属性文件。
一个例子:Windows 回收站。
在整个视窗系统中,回收站只能有一个实例,整个系统都使用这个惟一的实例,而且回收站自行提供自己的实例。因此,回收站是单例模式的应用。
两种形式:
1,饿汉式单例类
public class Singleton {
private Singleton(){}
//在自己内部定义自己一个实例,是不是很奇怪?
//注意这是private 只供内部调用
private static Singleton instance = new Singleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
2,懒汉式单例类
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。
JAVA单例模式的几种实现方法
单例模式1:
public
class
singleton{
private
static
singleton
st
=
null;
private
singleton(){
}
public
static
singleton
getinstance(){
if(st
==
null){
st
=
new
singleton();
}
return
st;
}
}
单例模式2:
public
class
singleton{
private
static
singleton
st
=
new
singleton();
private
singleton(){
}
public
static
singleton
getinstance(){
return
st;
}
}
多线程1:
导入thread所在的包
public
class
mythread1
extends
thread{
public
void
run(){
xxxxx写自己的代码
}
}
多线程2
导入runnable所在的包
public
class
mythread2
implements
runnable{
public
void
run(){
xxxxx写自己的代码
}
}
另写一个测试类,在main方法中这样写:
thread
t
=
new
mythread1();
或者
runnable
r
=
new
mythread2();
thread
t
=
new
thread(r);
单例模式的作用及创建方法
单例模式作为常见的设计模式之一,在java的项目开发中会时常的用到。Java Singleton模式即保证在JVM运行时,一个类Class只有一个实例存在。
单例模式有什么好处呢?
最简单的一个例子就是网站计数器的设计了。当我们想要统计当前网站的在线人数时,一个显而易见的问题就是并发所带来的线程安全问题,当我们对这个计数器(网站人数)在同一时刻进行操作,再保存计数时就会造成数据的混乱,后者覆盖前者的结果。一种解决方案就是把这个计数器设置为唯一对象,所有人都必须共用同一份数据。
实现唯一对象最好的解决办法就是让类自己负责保存它的唯一实例,并且让这个类保证不会产生第二个实例,同时提供一个让外部对象访问该实例的方法。自己的事情自己办,而不是由别人代办,这非常符合面向对象的封装原则。
单例模式的三个特点:
只有在自身需要的时候才会行动,从来不知道及早做好准备。它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。
该方法在多线程情况下有可能重复创建实例,以下是线程安全的懒汉模式
这种模式的缺点是加锁造成了效率下降,并且在绝大部分情况下是不需要同步的。使用双重检验锁(DCL),只在第一次初始化的时候进行同步加锁
该方式在类加载的时候就被实例化了。
这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟饿汉不同的是(很细微的差别):饿汉方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显式通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。
想象一下,如果实例化instance很消耗资源,我想让它延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式就显得很合理。
关于类加载情况下单例模式,如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类 装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。修复的办法是
如何在Java中实现单例模式?
单例模式1:
public
class
singleton{
private
static
singleton
st
=
null;
private
singleton(){
}
public
static
singleton
getinstance(){
if(st
==
null){
st
=
new
singleton();
}
return
st;
}
}
单例模式2:
public
class
singleton{
private
static
singleton
st
=
new
singleton();
private
singleton(){
}
public
static
singleton
getinstance(){
return
st;
}
}
多线程1:
导入thread所在的包
public
class
mythread1
extends
thread{
public
void
run(){
xxxxx写自己的代码
}
}
多线程2
导入runnable所在的包
public
class
mythread2
implements
runnable{
public
void
run(){
xxxxx写自己的代码
}
}
另写一个测试类,在main方法中这样写:
thread
t
=
new
mythread1();
或者
runnable
r
=
new
mythread2();
thread
t
=
new
thread(r);
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!";
}
}