java多线程(3)- 单例设计模式
2017-12-20 17:43
363 查看
什么是单例设计模式?
1_通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问。 这句话不好理解看代码
singleton_0e (种类介绍)
public class MyObject { //饿汉式 上来就干 private static MyObject myobject = new MyObject();//私有化 public static MyObject getInstance() { return myobject; } private MyObject() { } } /* 当我们使用class MyObject的实例时你会通过getInstancess 方法拿到唯一一个私有的静态的myobject对象。 */
不服来测试 打开多个线程直接打印对象的 hashCode值
** 可能会出现StackOverflowError
public class MyThread extends Thread { // @Override public void run() { System.out.println("MyObject类的实例化的对象 : " + MyObject.getInstance().hashCode()); } } @SuppressWarnings("all") class Run { public static void main(String[] args) { final MyThread t1 = new MyThread(); final MyThread t2 = new MyThread(); final 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) { } else { myObject = new MyObject(); } return myObject; } }
最后有个结果发生了变化!在多线程的情况下懒汉式会不唯一
singleton_0l_salve_synchronized
package cn.limbo.thread.singleton_0l_salve_synchronized; /** * 3个类都是针对懒加载 用synchronized的方式 */ public class MyObject { private static MyObject myObject; private MyObject() { } synchronized public static MyObject getInstance() { try { if (myObject != null) { } else { //模拟在创建对象之前做一些准备性的工作 Thread.sleep(3000); myObject = new MyObject(); } } catch (InterruptedException e) { e.printStackTrace(); } return myObject; } } class MyObject1 { private static MyObject1 myObject; private MyObject1() { } public static MyObject1 getInstance() { try { //此处的同步代码块访问的速度要快于同步方法的速度 //但是也是很慢 synchronized (MyObject1.class) { if (myObject != null) { } else { Thread.sleep(3000); myObject = new MyObject1(); } } } catch (InterruptedException e) { e.printStackTrace(); } return myObject; } } class MyObject2 { private static MyObject2 myObject; private MyObject2() { } public static MyObject2 getInstance() { try { if (myObject != null) { } else { Thread.sleep(3000); //仅仅只需要创建对象的时候加上同步锁 此方法可以得到大幅度提升 synchronized (MyObject2.class) { myObject = new MyObject2(); } } } catch (InterruptedException e) { e.printStackTrace(); } return myObject; } }
对synchronized在多线程下造成效率低下的改进
使用static代码实现单例模式
package cn.limbo.thread.singleton_0l_salve_static_block; /** * 使用static代码实现单例模式 * 静态代码块中的代码在使用类的时候就已经执行了 可以保证对象的唯一性 */ public class MyObject { private static MyObject instance = null; private MyObject() { } static { instance = new MyObject(); } public static MyObject getInstance() { return instance; } } class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(MyObject.getInstance().hashCode()); } } } @SuppressWarnings("all") class Run { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); /*485072371 485072371 485072371 485072371 485072371 485072371 485072371 485072371 485072371 485072371 485072371 485072371*/ } }
使用静态内置类来实现单例模式
package cn.limbo.thread.singleton_0l_salve_static_class; /** * 使用静态内置类来实现单例模式 */ public class MyObject { private static class MyObjectHandler { private static MyObject myObject = new MyObject(); } private MyObject() { } public static MyObject getInstance() { return MyObjectHandler.myObject; } } class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } } class Run { public static void main(String[] args) { MyThread[] myThreads = new MyThread[5]; for (int i = 0; i < myThreads.length; i++) { myThreads[i]=new MyThread() ; } for (int i = 0; i < myThreads.length; i++) { myThreads[i].start(); } } }
结论:静态内部类在类加载的时候就保证了单个对象
singleton_0l_salve_DCL_最火最常用DCL
package cn.limbo.thread.singleton_0l_salve_DCL; /** * DCL * 使用双检测来执行解决问题,即保证了不需要同步代码的异步执行性 * 又保证了单例的效果 */ public class MyObject_5 { //定义弱变量型来修饰 private volatile static MyObject_5 myObject_5; private MyObject_5() { } public static MyObject_5 getMyObject_5() { try { if (myObject_5 != null) { } else { Thread.sleep(3000); synchronized (MyObject_5.class) { if (myObject_5 == null) { myObject_5 = new MyObject_5(); } } } } catch (InterruptedException e) { e.printStackTrace(); } return myObject_5; } }
使用序列化和反序列化的单例模式实现
public class MyObject implements Serializable { private static final long serialVersionUID = 888L; private static class MyObjectHandler{ private static final MyObject myObject = new MyObject(); } public MyObject() { } public static MyObject getInstance(){ return MyObjectHandler.myObject; } /** * 这个代码的重要性 * 在实例化的过程中有这个方法代码 */ protected Object readResolve(){ System.out.println(" 调用了 readResolve方法"); return MyObjectHandler.myObject; } } class SaveAndRead{ public static void main(String[] args) throws Exception { MyObject myObject = MyObject.getInstance(); ///Users/lhh/Desktop FileOutputStream fosRef = new FileOutputStream(new File("/Users/lhh/Desktop/test001")); ObjectOutputStream oosRef = new ObjectOutputStream(fosRef); oosRef.writeObject(myObject); oosRef.close(); fosRef.close(); System.out.println(myObject.hashCode()); FileInputStream fisRef = new FileInputStream(new File("/Users/lhh/Desktop/test001")); ObjectInputStream isoRef = new ObjectInputStream(fisRef); MyObject myObject001 = (MyObject)isoRef.readObject(); isoRef.close(); fisRef.close(); System.out.println(myObject001.hashCode()); } }
用单例模式解决企业中SimpleDateFormat 出现的多并发异常
import java.text.SimpleDateFormat; public class DateTools { private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<SimpleDateFormat>(); public static SimpleDateFormat getSimpleDateFormat(String str) { SimpleDateFormat sdf = null; sdf = t1.get(); if (null == sdf) { sdf = new SimpleDateFormat(str); t1.set(sdf); } return sdf; } } package cn.limbo.thread.singleton_0l_SimpleDateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class MyThread extends Thread { private SimpleDateFormat sdf; private String dateString; public MyThread(SimpleDateFormat sdf, String dateString) { super(); this.sdf = sdf; this.dateString = dateString; } 9c3c @Override public void run() { try { final SimpleDateFormat simpleDateFormat = DateTools.getSimpleDateFormat("yyyy-MM-dd"); Date dateRef = simpleDateFormat.parse(dateString); String newDateString = simpleDateFormat.format(dateRef); if (!newDateString.equals(dateString)) { System.out.println(" 网站访问人数过多爆炸! " + "ThreadName= " + this.getName() + "报错的日期字符串: " + dateString + " 转换成的日期为: " + newDateString); } else { try { Thread.sleep(1000); System.out.println(" 小伙编写的代码 真几把 安全!" ); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (ParseException e) { e.printStackTrace(); } } } class Test { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String[] dateStringArray = {"2000-01-01", "2000-01-02", "2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06", "2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10",}; MyThread[] myThreads = new MyThread[10]; for (int i = 0; i < myThreads.length; i++) { myThreads[i] = new MyThread(sdf, dateStringArray[i]); } for (int i = 0; i < myThreads.length; i++) { myThreads[i].start(); } //无结果 没有异常 } }
相关文章推荐
- JAVA学习第二十五课(多线程(四))- 单例设计模式涉及的多线程问题
- 多线程环境下单例模式(java23中设计模式)
- 黑马程序员-------------多线程中的(线程、线程组、线程池、以及Java的设计模式)概念及方法的总结
- Java 多线程设计模式
- Java 多线程设计模式之Guarded Suspension
- java多线程中的设计模式
- 黑马程序员----------java基础加强之多线程、单例设计模式
- Java 多线程的设计模式之 Future
- JAVA学习第二十五课(多线程(四))- 单例设计模式涉及的多线程问题
- Java中的面试题 [3] --- Java高级知识、并发、多线程、JVM调优、分布式、设计模式等
- JAVA多线程的设计模式
- Java基础知识-多线程-设计模式-GUI
- Java单例设计模式,多线程下同步
- Java多线程之并发协作生产者消费者设计模式
- Java多线程之并发协作生产者消费者设计模式
- (一)java多线程编程设计模式之不可变模式
- java多线程-单例设计模式的问题及解决
- java 多线程设计模式之future
- Java_多线程、简单设计模式
- java 设计模式之单例模式(单线程、多线程下)