城乡建设学校官方网站如何给网站做301重定向

当前位置: 首页 > news >正文

城乡建设学校官方网站,如何给网站做301重定向,一个网站如何做cdn加速,wordpress 微信 登录界面文章目录 一、什么是设计模式#xff1f;二、单例模式2.1、饿汉模式2.2、懒汉模式2.3、多线程情况下调用 饿汉模式与懒汉模式 谁是安全的#xff1f;#xff1f;#xff08;重点#xff09; 三、工厂模式3.1、什么是工厂模式#xff1f;3.1.1、构造方法存在的缺陷3.1.1.1… 文章目录 一、什么是设计模式二、单例模式2.1、饿汉模式2.2、懒汉模式2.3、多线程情况下调用 饿汉模式与懒汉模式 谁是安全的重点 三、工厂模式3.1、什么是工厂模式3.1.1、构造方法存在的缺陷3.1.1.1、构造方法的名字必须固定是类名 一、什么是设计模式 设计模式就相当于菜谱有了菜谱/秘籍就能够根据菜谱上的指引/步骤做出许多从前不会的美食就算不会下厨的人拥有了食谱他的厨艺也能够得到提升和保障。 因此设计模式就是程序员的菜谱设计模式中介绍了许多典型场景以及针对这些典型场景的处理办法。按照设计模式来写的代码不会很差在一定的规范范围里。 设计模式有很多种不止23种今天主要介绍两种常见、常用的 1、单例模式 2、工厂模式 二、单例模式 单例模式对应的场景希望代码中的有些对象在整个程序中只有一个实例(即对象只能 new 一次)。 譬如说JDBC中的数据源DataSource这样的对象就只需要一个即可因此这个对象就可以使用单例模式。 对于我们程序员来说如果有些对象在整个程序中只需要有一个实例即可那我们程序员就只new一次就好了为什么还需要引入单例模式那是因为对于程序来说人是不靠谱的就需要引入单例模式此时由编译器来进行严格的检查对于代码中只能new一次的对象如果尝试new了多次编译器就会直接报错来进行提示确保某些对象处于单例模式。 接下来介绍一下在Java中单例模式的两种写法 2.1、饿汉模式 饿汉模式程序启动进行类加载之后立即创建出实例。比较迫切 代码例子 class Singleton{/*** 此处就期望类Singleton只有一个实例/// 静态成员instance // static 静态的与类相关的整个程序中只有一份private static Singleton instance new Singleton();// 通过此方法随时获取到刚刚的 instance 变量public static Singleton getInstance(){return instance;}// 作出限制禁止别人去 new 这个类的实例——将构造方法变成privateprivate Singleton(){} }public class testHunger {public static void main(String[] args) {Singleton s1 Singleton.getInstance();Singleton s2 Singleton.getInstance(); // 此时我们再new类的实例直接编译报错编译器校验了 // Singleton s3 new Singleton();// 我们可以发现 s1、s2 这两个都是同一个对象System.out.println(s1.equals(s2)); //true // s1、s2 和 s3 不是同一个对象 // System.out.println(s3.equals(s1)); //false // System.out.println(s3.equals(s2)); //false} }但是上述代码中我们将类的构造方法改成private此时别人就一定不能创建多个实例了吗其实还是可以通过 反射机制 在当前单例模式中创建出多个实例。 但是反射属于 “非常规” 的编程手段正常开发的时候慎重使用因为 滥用反射会给代码带来极大风险譬如会让代码变得抽象日后难以维护还破坏了Java的封装性。 当然Java中也有其他方式书写单例模式来防止反射但此处不做过多介绍可以自行查阅资料了解。 2.2、懒汉模式 懒汉模式第一次使用实例的时候才创建实例否则能不创建就不创建。比较佛系 /** 代码示例* 单例模式中的懒汉模式/ class SingletonLazy{private static SingletonLazy instance null;public static SingletonLazy getInstance(){if(instance null){instance new SingletonLazy();}return instance;}private SingletonLazy(){} }public class testLazy {public static void main(String[] args) {SingletonLazy s1 SingletonLazy.getInstance();SingletonLazy s2 SingletonLazy.getInstance();// 同样也是可以通过非常规手段反射机制 获取类的实例ClassSingletonLazy s3 SingletonLazy.class;System.out.println(s3.equals(s1));System.out.println(s1.equals(s2));} } 2.3、多线程情况下调用 饿汉模式与懒汉模式 谁是安全的重点 饿汉模式
懒汉模式 上述逻辑也是一个经典的面试题 那我们如何保证懒汉模式的线程安全呢 由于上述引起线程安全的原因是 if语句与new语句不是一个整体因此出现了线程安全问题此时我们通过将if语句和new语句打包成一个整体来解决懒汉模式的线程安全问题。 加锁之后线程在cpu上的执行流程当加了锁之后线程t2执行if语句时就会发现此时的instance是一个非null的值 虽然加了锁解决了线程安全问题但是还存在问题加锁是一个高成本的操作会引起阻塞等待。加锁的基本原则应该是非必要不加锁。不能无脑加锁如果无脑加锁就会导致程序的执行效率受到影响。 此时我们对懒汉模式的代码中加的锁导致后续每次调用 getInstance() 方法都要加锁但是这是不合理且不必要的。懒汉模式线程不安全主要是因为首次 new 对象时才存在的。一旦将对象 new 出来后后续再调用 getInstance() 方法就不存在线程安全问题了。但是我们现在的加锁是首次 new 对象调用时加锁了。后续调用也加锁了。但实际上后续调用不必加锁因为后续调用后if条件就进不去了此时也就不再涉及到修改操作了全是读操作。但我们把不该加锁的地方加上锁了很影响程序的执行效率。 对加锁操作做出以下修改
两个if语句之间存在加锁操作加锁就会引起线程阻塞等待究竟阻塞等待多久不知道有可能第一个if语句与第二个if语句间隔沧海桑田因此在这个长久的时间间隔里可能别的线程就把instance改了。 上述对加锁操作做了修改之后还存在一个问题 已知一般 instance new SingletonLazy()可以大致分成3个步骤 1、给对象创建出内存空间得到内存地址。 2、在空间上调用构造方法对对象进行初始化。 3、把内存地址赋值给 instance引用。
假设现在代码的执行顺序由123变成132但是在执行步骤3之后进行了线程切换此时还没来得及执行步骤2即给对象初始化就调度给别的线程了此时别的线程执行的时候判断instance不为空了于是就直接返回instance并且后续代码中可能会使用 instance 中的一些属性或者方法但是由于多线程下出现了指令重排序的问题导致线程安全问题此时的instance是个空引用即拿到的这个对象是个没有进行初始化不完整的对象。 解决办法给变量 instance 加上 volatile 之后此时针对 instance 的赋值操作就不会产生上述的指令重排序了其执行顺序必然是遵循1、2、3执行。 加上 volatile 还有一个另外的用途避免此处赋值操作的指令重排序。 懒汉模式的最终代码版本 /**
代码示例* 单例模式中的懒汉模式*/ class SingletonLazy{private static volatile SingletonLazy instance null;public static SingletonLazy getInstance(){if (instance null){synchronized (SingletonLazy.class){if(instance null){instance new SingletonLazy();}}}return instance;}private SingletonLazy(){} }public class testLazy {public static void main(String[] args) {SingletonLazy s1 SingletonLazy.getInstance();SingletonLazy s2 SingletonLazy.getInstance();// 同样也是可以通过非常规手段反射机制 获取类的实例ClassSingletonLazy s3 SingletonLazy.class;System.out.println(s3.equals(s1));System.out.println(s1.equals(s2));} }懒汉模式代码的3大要点 1、加锁 2、双重if 3、volatile 从字面上理解/区分 饿汉模式和懒汉模式 会比较抽象举2个例子加深一下理解 譬如说日常生活中吃完饭之后需要洗碗有的人习惯吃完饭后立即洗碗有的人习惯吃完饭后将碗放到一边等到下顿饭要吃的时候才洗碗。一般大家会觉得吃完饭之后立即洗碗是一种高效率的生活方式但其实在不考虑卫生的情况下吃完饭后不洗碗等到下次开饭再洗碗然后接着用其实效率会更高。比如说这顿吃完有4个碗下顿开饭只需要用到2个碗此时就只需要洗2个碗来用就行了效率大大提高了。 还譬如说假设编辑器打开一个很大的文件有的编辑器会一下尝试把所有内容都加载到内存中再显示出来这是典型的饿汉模式。有的编辑器则只加载一部分内容一个屏幕能显示的内容其他部分当用户翻页想要浏览时再加载出来这是典型的懒汉模式。 三、工厂模式 3.1、什么是工厂模式 工厂顾名思义是用来生产的。那么对应到我们代码上工厂模式就是用来生产对象的。那么具体是怎么进行生产对象的呢一般我们创建对象都是通过 new 的形式使用构造方法来把对象创建出来但构造方法存在一些缺陷因此此时就可以使用 工厂模式 解决 上述问题。 3.1.1、构造方法存在的缺陷 3.1.1.1、构造方法的名字必须固定是类名 但是有时候有的类需要多种不同的构造方式可由于构造方法名必须与类名一致此时就只能使用方法重载参数的个数和类型需要有差别的方式来区分了。 譬如有一个坐标系类 Point。在此类中想要通过两种构造方式进行创建对象一种是笛卡尔坐标系构造一种是按照极坐标构造 public class Point{public Point(double x,double y){}public Point(double r,double a){} } 这两种构造方式的意义并不一样但是使用构造方法表示出来时由于其参数个数和类型都一致因此无法构成方法重载因此上述代码就会直接编译报错。那此时就可以使用工厂模式来解决上述问题1、即不使用构造方法了使用普通的方法来构造对象这样方法名字就可以是任意的了。2、在普通方法的内部再来new对象。 由于普通方法的目的是为了创建出对象来因此这样的普通方法一般得是静态的。因为要创建实例却又依赖实例因此这样的普通方法设定为 静态的 public class Point{ //由于这两方法的方法名不同此时不会编译报错public static makePointXY(double x,double y){//我们再在方法内部 new 出对象Point p Point.makePointXY(10,20);}public static makePointRA(double r,double a){} }这样的操作我们就称为 “工厂模式”这样的方法我们就称为 “工厂方法”