关于单例模型的一点困惑解答

---恢复内容开始---

首先我没来看看比较普遍的单例模式下的线程问题

     创建一个单例类

    

package com.test;

public class test {
    
	private static test t;
	
	private test(){
		System.out.println("我初始化了.....");
	}
	
	public static test getInstance(){
		if(t == null){
			t = new test();
		}
		return t;
	}
	
	public void run(String str){
		System.out.println("run()..." + str);
	}
}

  然后创建一个测试类

 

package com.test;

public class mainTest {

	public static void main(String[] args) {
		test.getInstance().run("在一个线程下1");
		test.getInstance().run("在一个线程下2");
	}
}

  运行结果

我初始化了.....
run()...在一个线程下1
run()...在一个线程下2

  证明在同一个线程下这种方式的单例模式确实能做到单例的存在

    下面看看在不同线程中

package com.test;

public class mainTest {

	public static void main(String[] args) {
//		test.getInstance().run("在一个线程下1");
//		test.getInstance().run("在一个线程下2");
		
		new Thread(new Runnable() {
			public void run() {
				// TODO Auto-generated method stub
				test.getInstance().run("在一个线程下1");
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run() {
				// TODO Auto-generated method stub
				test.getInstance().run("在一个线程下2");
			}
		}).start();
		
		
	}
}

  运行结果

我初始化了.....
run()...在一个线程下1
我初始化了.....
run()...在一个线程下2

  在不同线程中就不存在单例的模式了

 

     下面我们看看通过静态内部类来实现

package com.test;

public class test {
    
	private static test t;
	
	private test(){
		System.out.println("我初始化了.....");
	}
	
	public static test getInstance(){
		return instance.t;
	}
	
	public static class instance{
		public static test t = new test();
	}
	
	public void run(String str){
		System.out.println("run()..." + str);
	}
}

  下面测试一下在单线程中

package com.test;

public class mainTest {

	public static void main(String[] args) {
		test.getInstance().run("在一个线程下1");
		test.getInstance().run("在一个线程下2");
		
//		new Thread(new Runnable() {
//			public void run() {
//				// TODO Auto-generated method stub
//				test.getInstance().run("在一个线程下1");
//			}
//		}).start();
//		
//		new Thread(new Runnable() {
//			public void run() {
//				// TODO Auto-generated method stub
//				test.getInstance().run("在一个线程下2");
//			}
//		}).start();
		
		
	}
}

  运行结果

我初始化了.....
run()...在一个线程下1
run()...在一个线程下2

  单例没问题 那在多线程中呢

package com.test;

public class mainTest {

	public static void main(String[] args) {
//		test.getInstance().run("在一个线程下1");
//		test.getInstance().run("在一个线程下2");
		
		new Thread(new Runnable() {
			public void run() {
				// TODO Auto-generated method stub
				test.getInstance().run("在一个线程下1");
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run() {
				// TODO Auto-generated method stub
				test.getInstance().run("在一个线程下2");
			}
		}).start();
		
		
	}
}

  还是单例的

我初始化了.....
run()...在一个线程下1
run()...在一个线程下2

  好了我也是在写这篇博客的时候才恍然大悟,可能你会觉得我很菜,确实很菜,这种简单的问题都想不明白,看来越是基础越难懂,但是当基础懂了之后就不同了

我先来分析一粗略的原因 因为前一种并没有在声明静态变量的时候创建对象 所以在对象加载的时候堆中并没有对象存在,当线程运行时候发现没有对象所以创建对象,由于对象是在线程中创建的所以栈中和堆中的对象对应,因为栈是线程私有的,所以当另一个线程去访问类的变量的时候,还是没有,所以还是要自己创建对象所以就创建了两次,但是在类上面直接创建对象的时候每次线程去取的时候堆中都有一个与之对应的所以就是多线程中的私有的。好吧,有点乱我自己都还是不太懂!

     

---恢复内容结束---

posted @ 2016-03-25 10:59  小琪子  阅读(198)  评论(0)    收藏  举报