Java多线程学习(四)
2016-03-06 19:36
405 查看
单例模式
1.1立即加载/饿汉模式
立即加载既为使用类的方法的时候已经将对象创建完毕。常见的实现方法就是直接new实例化。
延迟加载既为调用类的方法时,对象实例才被创建。常见实现方法为在get方法中进行new实例化。
延迟加载的解决方案
如上例所示的延迟加载方法,在多线程模式下是线程不安全的,那么就是以下几种解决方案吧!
①声明synchronized关键字
既然出现线程不安全问题是因为多个线程同时进入getInstance方法导致的,那么就给这个方法上锁,同一时间内只有一个线程能够访问。
②尝试同步代码块
③尝试给重要代码上锁
④使用DCL双检查锁机制
1.1立即加载/饿汉模式
立即加载既为使用类的方法的时候已经将对象创建完毕。常见的实现方法就是直接new实例化。
public class MyObject { private static MyObject myObject = new MyObject(); private MyObject(){} public static MyObject getInstance(){ return myObject; } } public class MyThread extends Thread { public void run(){ System.out.println(MyObject.getInstance().hashCode()); } public static void main(String [] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 运行结果为三个线程输出的值相同。1.2延迟加载/懒汉模式
延迟加载既为调用类的方法时,对象实例才被创建。常见实现方法为在get方法中进行new实例化。
public class MyObject { private static MyObject myObject; private MyObject(){} public static MyObject getInstance(){ if(myObject == null){ myObject = new MyObject();} return myObject; } } public class MyThread extends Thread { public void run(){ System.out.println(MyObject.getInstance().hashCode()); } public static void main(String [] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 运行结果为三个线程输出的值不同,取出了多个线程实例,与单例模式相违背。
延迟加载的解决方案
如上例所示的延迟加载方法,在多线程模式下是线程不安全的,那么就是以下几种解决方案吧!
①声明synchronized关键字
既然出现线程不安全问题是因为多个线程同时进入getInstance方法导致的,那么就给这个方法上锁,同一时间内只有一个线程能够访问。
public class MyObject { private static MyObject myObject; private MyObject(){} synchronized public static MyObject getInstance(){ if(myObject == null){ myObject = new MyObject(); } return myObject; } } public class MyThread extends Thread { public void run(){ System.out.println(MyObject.getInstance().hashCode()); } public static void main(String [] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 运行结果为三个线程输出的值相同。但是这种方法的运行效率非常低下。
②尝试同步代码块
public class MyObject { private static MyObject myObject; private MyObject(){} public static MyObject getInstance(){ synchronized (MyObject.class){ if(myObject == null){ myObject = new MyObject();} } return myObject; } } public class MyThread extends Thread { public void run(){ System.out.println(MyObject.getInstance().hashCode()); } public static void main(String [] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 运行结果为三个线程输出的值相同。但是这相当于第一种给方法上锁的方式,效率同样低下。
③尝试给重要代码上锁
public class MyObject { private static MyObject myObject; private MyObject(){} public static MyObject getInstance(){ if(myObject == null){ synchronized (MyObject.class){ myObject = new MyObject(); } } return myObject; } } public class MyThread extends Thread { public void run(){ System.out.println(MyObject.getInstance().hashCode()); } public static void main(String [] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 运行结果为三个线程输出的值不相同,并不是单例的。这样的上锁方式虽然虽然提高了效率,但是仍有可能同时有多个线程进入if方法内部,等待执行同步代码块,因此获取了多个对象。
④使用DCL双检查锁机制
public class MyObject { private static MyObject myObject; private MyObject(){} public static MyObject getInstance(){ if(myObject == null){ synchronized (MyObject.class){ if(myObject == null){ myObject = new MyObject(); } } } return myObject; } } public class MyThread extends Thread { public void run(){ System.out.println(MyObject.getInstance().hashCode()); } public static void main(String [] args){ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 运行结果为三个线程输出的值相同。使用双重检查锁机制,成功的解决了懒汉模式遇到多线程的问题。DCL也是大多数多线程结合单例模式使用的解决方案。
相关文章推荐
- 修改maven配置默认jdk版本
- 《疯狂Java讲义》——控制线程
- 下载eclipse
- ubuntu下Eclipse安装
- 重新认识java-LinkedList
- 《Java程序设计》第1周学习总结
- Java线程状态
- JAVA-内部类
- 【JAVA集合】ArrayList
- org.springframework.beans.factory.CannotLoadBeanClassException
- 使用spring webflow遇到的问题-3
- Java开发文档的使用与Hashcode的入门(老鸟勿进)
- [学习笔记】Java Numbers类与Math类
- Java并发编程笔记 Native方法,CAS操作与ABA问题
- (java) Single Number II
- Spring MVC之@PathVariable @RequestHeader, @CookieValue@RequestParam @RequestBody @RequestHeader 等详解
- eclipse调试
- Java-猜拳游戏
- Spring JDBC 例子
- struts2学习笔记-------为action的属性注入值