单例模式1:
package synchro;
public class Singleton {
private Singleton(){}
private static Singleton instance;
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
return instance;
}
return instance;
}
public static void main(String[] args) {
for(int i=0;i<1000;i++){
Thread t=new GetClassInfo();
t.setName("线程"+i);
t.start();
}
}
}
class GetClassInfo extends Thread{
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println(getName()+"获取单例模式:"+Singleton.getInstance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
第一种singleton是比较常用的一种单例模式,如果同时有多个线程一起获取这个单例对象的话,可能会出现问题。
1000个线程访问这个对象的结果:
线程2获取单例模式:synchro.Singleton@151574b
线程1获取单例模式:synchro.Singleton@151574b
线程0获取单例模式:synchro.Singleton@151574b
线程3获取单例模式:synchro.Singleton@1d2052b
线程4获取单例模式:synchro.Singleton@1187984
线程6获取单例模式:synchro.Singleton@151574b
线程5获取单例模式:synchro.Singleton@151574b
线程7获取单例模式:synchro.Singleton@151574b
线程10获取单例模式:synchro.Singleton@151574b
可以看到线程3和4分别获取了不同的实例,所以这个单例的写法有缺点。
单例模式2:
package synchro;
public class Singleton2 {
private Singleton2(){}
private static Singleton2 instance=new Singleton2();
public static Singleton2 getInstance(){
return instance;
}
public static void main(String[] args) {
for(int i=0;i<1000;i++){
Thread t=new GetClassInfo2();
t.setName("线程"+i);
t.start();
}
}
}
class GetClassInfo2 extends Thread{
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println(getName()+"获取单例模式:"+Singleton2.getInstance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
饿汉模式:
用饿汉模式试了上万遍,没出现不同实例的问题,除了类加载后就创建对象外,这个难道是不会出现线程安全问题的单例模式吗?
单例模式3:
public class Singleton3 {
private Singleton3(){}
private static Singleton3 instance;
public synchronized static Singleton3 getInstance(){
if(instance==null){
instance= new Singleton3();
}
return instance;
}
}
sychronized修饰方法:试了上万次,也没有发现出现多个实例的问题。。
单例模式4:
public class Singleton4 {
private Singleton4(){}
private static Singleton4 instance;
public static Singleton4 getInstance(){
if(instance==null){
synchronized (Singleton4.class) {
if(instance==null){
instance=new Singleton4();
}
}
}
return instance;
}
}
使用synchronized代码块包裹new实例的部分,自己用循环一共测试了2万遍,没有发现出现不同实例的情况。
单例模式5:
public class Singleton4 {
private Singleton4(){}
private volatile static Singleton4 instance;
public static Singleton4 getInstance(){
if(instance==null){
synchronized (Singleton4.class) {
if(instance==null){
instance=new Singleton4();
}
}
}
return instance;
}
}
用volatile修饰静态实例,这个没有测试,网上说这个方法是最好的一种写法。需要用好的办法证明一下。
总结:
除了用第一种懒汉单例模式进行测试出现了多个实例的情况,其他几种各测试了上万次(用循环),基本没有出现多个实例的情况。由于本人工作经验才4个月,又是通过培训中心培训出来的,所以技能肯定有所欠缺,麻烦看官能够指出我的错误。。