标签:uri 使用方法 复制 rri jdk int 输出 多用户 用户
单例模式是JAVA设计模式中最常用、最重要的设计模式之一。
最简单的写法是:
public class TestSingleton { private static String ourInstance = null; //私有化构造器 private TestSingleton() { } //提供静态方法给外部访问 public static String getOurInstance(){ if(ourInstance == null){ ourInstance="单例模式赋值成功!!!"; System.out.print(ourInstance); } return ourInstance; } }
这种写法的单例模式是线程不安全的,下面用代码来模拟一下多线程并发,代码的执行情况:
public class Test { /** * 线程池 */ final static ExecutorService threadPool = Executors.newCachedThreadPool(); /** * 并发数 */ private final static int CONCURRENT_COUNT = 10; /** *同步工具类? */ final static CountDownLatch locks = new CountDownLatch(CONCURRENT_COUNT); public static void main(String[] args) { for (int i = 0; i < CONCURRENT_COUNT; i++) { threadPool.execute(new Runnable() { @Override public void run() { locks.countDown(); TestSinleton.getOurInstance(); } } ); } } }
代码非常简单,用线程池执行CONCURRENT_COUNT 个任务,每个任务执行到
locks.countDown()
时被阻塞,当被阻塞的任务数达到CONCURRENT_COUNT个时,所有任务同时往下执行,这样模拟了多个用户并发的场景。(CountDownLatch 的使用方法)
思考:如果以上写法的单例模式线程安全,那么控制台只会打印一次:单例模式赋值成功!!!
运行3次程序,查看控制台输出:
"C:\Program Files\Java\jdk1.8.0_101\bin\java" ... 单例模式复制成功!!!单例模式复制成功!!! Process finished with exit code 0
"C:\Program Files\Java\jdk1.8.0_101\bin\java" ... 单例模式赋值成功!!!单例模式赋值成功!!!单例模式赋值成功!!! Process finished with exit code 1
"C:\Program Files\Java\jdk1.8.0_101\bin\java"... 单例模式赋值成功!!! Process finished with exit code 1
发现并不是想的这样,很容易就出现了变量被多次赋值的情况。所以,以上的单例模式是线程不安全的。
思考为什么会出现这种情况?
因为多用户并发操作的情况下,if(ourInstance == null) 可能被同时执行,如果ourInstance为空的话,就会出现多个线程判断(ourInstance == null)为true了。
修改代码:
public class TestSinleton { private static String ourInstance = null; //私有化构造器 private TestSinleton() { } //提供静态方法给外部访问 public static String getOurInstance(){ if(ourInstance == null){ synchronized (TestSinleton.class){ if(ourInstance == null){ ourInstance="单例模式复制成功!!!"; System.out.print(ourInstance); } } //ourInstance="单例模式赋值成功!!!"; //System.out.print(ourInstance); } return ourInstance; } }
第一次判空,大部分线程被挡掉。继续往下是一个synchronized 方法,只允许单线程执行,所以第二次判空就不会存在多个线程同时执行的情况。
多次运行程序,查看控制台:
"C:\Program Files\Java\jdk1.8.0_101\bin\java" ... 单例模式复制成功!!! Process finished with exit code 0
发现只会打印一次了。
标签:uri 使用方法 复制 rri jdk int 输出 多用户 用户
原文地址:http://www.cnblogs.com/newstudent/p/java_singleton.html