1.饿汉式
立即加载,随着类而加载创建
优点:写法简单、在内存中加载较早,使用起来方便安全。而且线程是安全的。
缺点:在内存中占用时间长
public class danxiancheng {
public static void main(String[] args) {
gril aa = gril.getBank();
System.out.println(aa.a);
gril bb =gril.getBank();
}
}
class gril{
int a;
private gril() {
}
private static gril bank = new gril();//饿汉式
public static gril getBank(){
return bank;
}
}
线程安全测试:
class test{
static man m1 = null;
static man m2 = null;
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
m1 =man.getM1();
}
};
Thread t2 = new Thread(){
@Override
public void run() {
m2=man.getM1();
}
};
t1.start();
t2.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(m1);
System.out.println(m2);
System.out.println(m1 == m2);
}
}
class man{
private static man m1 = new man();//饿汉式,提前实例化man对象,并且唯一
static man getM1() {
return m1;
}
}
运行结果:
chapter_9.man@1b6d3586
chapter_9.man@1b6d3586
true
2.懒汉式
延迟加载,在需要的时候加载创建
优点:在需要的时候创建,节省了内存空间
缺点:线程不安全
public class danxiancheng {
public static void main(String[] args) {
gril a1 = null;
gril aa= gril.getbank(a1);
System.out.println(aa);
}
}
class gril{
int a;
//构造器私有化
private gril() {
}
//声明当前类的实列
private gril bank =null;
//通过getbank获得当前类的实列,如果为null对当前类实列话,否则返回当前类实列
public static gril getbank(gril cbank){
if(cbank == null){
cbank = new gril();
}
return cbank;
}
}
线程安全测试:
class test{
static man m1 =null;
static man m2 =null;
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
m1 = man.getM1();
}
};
Thread t2 = new Thread(){
@Override
public void run() {
m2 = man.getM1();
}
};
t1.start();
t2.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(m1);
System.out.println(m2);
System.out.println(m1 == m2);
}
}
class man{
private static man m1 =null;
static man getM1() {
if(m1 == null){
m1 = new man();
}
return m1;
}
}
测试结果:
chapter_9.man@1b6d3586
chapter_9.man@4554617c
false
解决方法:synchronized同步
static synchronized man getM1() {//关注this是否唯一,此时有statci,所以man.class唯一
if(m1 == null){
m1 = new man();
}
return m1;
}
or
static man getM1() {
synchronized (man.class) {
if(m1 == null){
m1 = new man();
}
return m1;
}
}
//相比以上优化
private static volatile man m1 =null;//为了避免指令重排,使用volatile声明m1
or//加入lock
lock.lock();
if(m1 == null){
m1 = new man();
}
return m1;
lock.unlock();