本人在复习准备OCJP认证,遇到这样一道考题
Given:
2. class SafeDeposit {
3. private static SafeDeposit singleton;
4. public static SafeDeposit getInstance(int code) {
5. if(singleton == null)
6. singleton = new SafeDeposit(code);
7. return singleton;
8. }
9. private int code;
10. private SafeDeposit(int c) { code = c; }
11. int getCode() { return code; }
12. }
13. public class BeSafe {
14. // insert lots of code here
25. }
Given:
2. class SafeDeposit {
3. private static SafeDeposit singleton;
4. public static SafeDeposit getInstance(int code) {
5. if(singleton == null)
6. singleton = new SafeDeposit(code);
7. return singleton;
8. }
9. private int code;
10. private SafeDeposit(int c) { code = c; }
11. int getCode() { return code; }
12. }
13. public class BeSafe {
14. // insert lots of code here
25. }Which are true? (Choose all that apply.)
A. Compilation fails.
B. Class BeSafe can create many instances of SafeDeposit.
Assessment Test 2: Answers 51
C. Class BeSafe CANNOT create any instances of SafeDeposit.
D. Class BeSafe can create only one instance of SafeDeposit.
E. Class BeSafe can create instances of SafeDeposit without using the getInstance()
method.
F. Once class BeSafe has created an instance of SafeDeposit, it cannot change the value
of the instance’s "code" variable.正确答案是:BF,理由是BeSafe可以多线程。请问一下:
BeSafe类既没有extends Thread,也没有implments Runnable,它怎么多线程呢?
我猜想有可能是通过内部线程类来启动多线程,但我模拟的结果表明:singleton只能被实例化一次,将代码贴上来。求指教package com.qp.singleton;class SafeDeposit{

private static SafeDeposit singleton;

public static SafeDeposit getInstance(int code){
if(singleton==null){
System.out.println("SafeDeposit>>>> "+code);
singleton = new SafeDeposit(code);
}
return singleton;
}

private int code; public int getCode() {
return code;
} private SafeDeposit(int code) {
super();
this.code = code;
}
}public class BeSafe {
public static void main(String[] args) {
BeSafe bs1 = new BeSafe();
TestMultipleThread child1 = bs1.new TestMultipleThread(1);
Thread t1 = new Thread(child1);
t1.start();
BeSafe bs2 = new BeSafe();
TestMultipleThread child2 = bs2.new TestMultipleThread(2);
Thread t2 = new Thread(child2);
t2.start();
}

class TestMultipleThread implements Runnable{

int c;

public TestMultipleThread(int c) {
super();
this.c = c;
} @Override
public void run() {
SafeDeposit sd = SafeDeposit.getInstance(c);
System.out.println(c);
}

}
}OCJP多线程Singleton

解决方案 »

  1.   

    呵呵,一个设计单例模式中的双重检查锁定 考题。
    首先,您的理解不准确,不是指BeSafe类 实现多线程,而是说这个类在多线程环境下使用,创建时可能产生多个实例。
    其次:创建了多个实例了代码/**
     * 线程不安全的单例模式
     * 
     * @author newthinking
     *
     */
    public class Singleton {
    private static Singleton instance=null;
    private Singleton(){

    }
    /**
     * 模拟网络延时,方便看到多线程中创建了不同的对象
     * @param time 在多线程中指定时间,用于控制延时
     * @return
     */
    public static Singleton getInstance(int time){
    if(null==instance){
    try {
    //模拟网络延时
    Thread.sleep(time);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    instance = new Singleton();
    }
    return instance;
    }

    }/**
     * 线程
     * @author newthinking
     *
     */
    public class TestMultiInstance  implements Runnable{
    private Singleton single =null;
    private int time; //延时的时间
    TestMultiInstance(int time){
    this.time =time;
    }
    @Override
    public void run() {
    //创建对象
    single =Singleton.getInstance(time);
    //查看地址
    System.out.println(single);
    }}/**
     * 测试类
     * @author newthinking
     *
     */
    public class App { /**
     * @param args
     */
    public static void main(String[] args) {
    new Thread(new TestMultiInstance(200)).start();
    new Thread(new TestMultiInstance(100)).start();
    }}
    由于模拟了延时,二者的地址不同了,违背了单例的原则:只能存在一个实例
      

  2.   

    使用双重检查锁定(Double-Check Locking ) 改进单例类/**
     * 线程安全的单例模式
     * 
     * @author newthinking
     *
     */
    public class Singleton {
    private static Singleton instance=null;
    private Singleton(){

    }
    /**
     * 模拟网络延时,方便看到多线程中创建了不同的对象
     * @param time 在多线程中指定时间,用于控制延时
     * @return
     */
    public static Singleton getInstance(int time){
    if(null==instance){ //这句话可以没有,但是为了提高性能而加上的
    synchronized(Singleton.class){ //加入了锁机制
    if(null==instance){
    try {
    //模拟网络延时
    Thread.sleep(time);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    instance = new Singleton();
    }
    }
    }
    return instance;
    }

    }
      

  3.   

    改进之后的单例,就没有问题了。当然创建单例最简单的还是下面的代码:/**
     * 线程安全的单例模式
     * 
     * @author newthinking
     *
     */
    public class Singleton {
    private static Singleton instance=new Singleton();
    private Singleton(){

    }

    public static Singleton getInstance(int time){
    return instance;
    }

    }