单例模式的线程安全实现方法及其优缺点
第一种方式
public class SigleM {
private static User user=new User();
public static User newinstance(){
return user;
}
}
这种方式的优点:线程安全,在类被加载的时候,就已经创建好了一个静态的对象
这种方式的缺点:对象在没有使用的时候已经被创建出来了
第二种方式
public class SigleM {
private static User user=null;
public static User newinstance(){
if (user==null) {
user = new User();
}
return user;
}
}
这种方式的优点:按需求创建对象,只有对象被使用的时候才会创建
这种方式的缺点:非线程安全,在多线程情况下,可能会创建多个对象
第三种方式
public class SigleM {
private static User user=null;
public static User newinstance(){
if (user==null) {
synchronized (User.class) {
if (user == null) {
user = new User();
}
}
}
return user;
}
}
这种方式是对第二种的改进
优点:按需求创建对象,只有对象被使用的时候才会创建,并且,他是线程安全的,在多线程情况下,不会产生多个对象。
给出一个测试类,用来测试上面三种单例模式的实现
public class Test {
public static void main(String[] args) {
Thread thread=new Thread(new Hehe());
thread.start();
Thread thread2=new Thread(new Dada());
thread2.start();
}
}
class Hehe implements Runnable{
@Override
public void run() {
User user=SigleM.newinstance();
System.out.println("hehe-->"+user.toString());
}
}
class Dada implements Runnable{
@Override
public void run() {
User user=SigleM.newinstance();
System.out.println("dada-->"+user.toString());
}
}
测试结果如下
第一种:
dada-->User@7e437185
hehe-->User@7e437185
第二种:
hehe-->User@570d413f
dada-->User@60174d9
第三种:
hehe-->User@6299d4f3
dada-->User@6299d4f3
根据多次测试情况可知,第二种方式确实为非线程安全。