package com.iotek.threadtest;
2
3 public class SingleTonDemo {
4
5 /** 单例模式:
6 * 单例模式有饿汉模式和懒汉模式,懒汉式即延迟初始化单例.
7 * 在多线程环境下,简单的懒汉式会有线程安全的困扰
8 * 下面通过设计程序来实现线程安全的懒汉式单例模式:
9 * 1.实现懒汉式单例模式
10 * 2.使用双重检查加锁机制解决线程安全问题
11 * 3.单例模式还有更好的解决方案,即使用静态类方式
12 * @param args
13 * @version14 */
15 public static void main(String[] args) {
16 SingleTon.getInstance();
17 SingleTon.getInstance();
18 // 上面调用2次getInstance()方法,但构造方法里的语句只打印了一次,说明只产生了一个对象
19 SThread sThread = new SThread(); // 创建一个Runnable接口的实现类对象
20 Thread t1 = new Thread(sThread);
21 t1.start();
22 /*
23 * 线程的创建方式2: 创建一个Thread类对象,将Runnable接口的实现类(对象)作为 实际参数传入Thread类的构造方法 3.重写
24 * Runnable 接口中的run()方法
25 */
26 Thread t2 = new Thread(sThread);
27 t2.start();
28 }
29
30 }
31
32 class SThread implements Runnable {
33
34 @Override
35 public void run() {
36 SingleTon.getInstance();
37 }
38
39 }
40
41 class SingleTon {
42 private static SingleTon singleTon = null;
43 // 单例模式中,要返回的这个singleTon对象必须是static的,
44
45 private SingleTon() {
46 System.out.println("单例模式");
47 }
48
49 public static SingleTon getInstance() {
50 // static:要想外部程序访问,只能设为静态的,静态方法只能访问静态变量,所以属性也要设置为静态的
51 if(singleTon ==null) {
52 //只有singleTon变量为null时,才执行同步块,否则直接返回singleTon变量
53 synchronized (SingleTon.class) {
54 if (singleTon == null) {
55 singleTon = new SingleTon();
56 }
57 }
58 }
59 return singleTon;
60 }
61 }
62
63 /*
64 * if (singleTon == null) { singleTon = new SingleTon(); }
65 * 分析这段代码,当第一个线程程序执行了singleTon == null,还未执行 singleTon = new SingleTon();
66 * 语句时,第二个线程此时如果也执行到了singleTon == null判断语句,那么将会再次调用 singleTon = new SingleTon();
67 * 语句,这样的话会2次产生对象,这样就会造成线程非安全操作,该如何避免这种情况? 只需将这段代码放到同步块synchronized (singleTon)
68 * {} 中 ,那么此处对象锁该使用哪个锁呢? 要想多个线程都使用这个对象的锁,那么需要使用一个共同的锁,可以用SingleTon.class这个对象的锁
69 */
70
71 /* 当第一个线程进入同步块后,获得了SingleTon.class这个对象的锁,
72 * 第二个线程只能等待,只有当第一个线程执行完代码将锁释放后,第二个
73 * 线程获得该锁 才能启动第二个线程,第二个线程进来,判断 singleTon == null
74 * 条件不满足,直接跳过new语句,执行return singleTon; 语句,但是这样会有
75 * 一个问题,第一个线程已经产生了一个对象之后,其他的线程就没必要再进来了,
76 * 也就是说没必须要再执行同步块,因此在外层再添加一个判断,只有当singleTon
77 * 这个引用变量为null时,才执行同步块,否则直接返回singleTon引用变量!!!
78 * */
单例模式要点:
静态属性:private static SingleTon singleTon = null;
构造方法私有化:private SingleTon(){}
对外提供静态的获取实例的方法:public static SingleTon getInstance() {}