一、单例模式中的多线程问题
1、单例模式的俩种情况
单例模式分:饿汉式(先加载的单例设计模式)、懒汉式(延迟加载的单例设计模式)俩种。
2、饿汉式时的多线程问题
public class Single {
private static final Single s = new Single();
private Single(){}
private static Single getInstance(){
return s;
}
}
此模式在多线程下执行getInstance()方法时,是没有安全隐患的。因为它返回的s就是共享变量。
3、懒汉式时的多线程问题
public class SingleDoem {
private static Single s = null;
private SingleDoem(){}
private static Single getInstance(){
if(s == null){
s = new Single();
}
return s;
}
}
此模式在多线程下执行getInstance()方法时,是有安全隐患的。当一个线程刚执行完第7行代码时,第二个线程再执行第7代码时也会进入判断语句中;这样,第一个线程返回的是一个新的Single对象,而第二个线程返回的也是一个新的Single对象,这就违法了单例设计模式。
4、解决懒汉式时的多线程问题
- 在延迟加载模式的getInstance方法上加synchronized关键字即可
public class SingleDoem {
private static Single s = null;
private SingleDoem(){}
private static synchronized Single getInstance(){
if(s == null){
s = new Single();
}
return s;
}
}
但这个办法是以牺牲效率来拯救多线程的安全。下面的方法,可以在保证多线程安全的情况下,再提示效率
- 使用同步代码,并在其之前进行判断
public class SingleDoem {
private static Single s = null;
private SingleDoem(){}
private static Single getInstance(){
if(s == null){
synchronized (SingleDoem.class) {
if(s == null){
s = new Single();
}
}
}
return s;
}
}
总结:“synchronized (SingleDoem.class)”是为了多线程安全;
第一个“if(s == null)”=是用于拯救效率;
二、多线程相关面试题
1、以下代码会打印的语句是?
class Thread{
public static void mian(String[] args){
new Thread(new Runnable(){
public void run(){
System.out.println("runnable run");
}
}){
public void run(){
System.out.println("subThread run");
}
}.start();
}
答:以子类为主。即,subThread run。然后是Runnale的run()方法,最后是Thread自己的run()方法。
2、以下代码在编译的时候,是否会出现错误?如果会,错误出现在哪行?
class Test implements Runnable{
public void run(Thread t){
}
}
答:会出错,错误在第一行。因为未实现Runnable接口的run()方法。