1什么是创建型设计模式?
处理对象创建的模式,简答的理解就是如何创建对象?很多人都会想到new关键字,一般的项目你到处new是不会有问题的,但是稍微复杂一点的项目,可能需要考虑到对象的单一性、复用性和可扩展性。
为什么要有单例模式?2.常见的单例模式
单例模式可以提供一种简单而有效的方式来管理和访问全局资源,同时也可以提高系统的性能和可维护性
举一个案例,如果你需要一个全局的缓存(现在好多大数量级的都采用redis),那么这个缓存就只能存在一个实例对象中,理解下。当然总结下来:
- 节省资源:由于单例模式只创建一个实例,可以节省系统资源,特别是在需要频繁创建和销毁对象的情况下。
- 全局访问点:单例模式提供了一个全局访问点,可以方便地访问实例,避免了在不同的地方重复创建实例的问题。
- 数据共享:由于单例模式只有一个实例,可以方便地在不同的对象之间共享数据。
- 线程安全:单例模式可以确保在多线程环境下只有一个实例被创建,避免了多线程竞争的问题。
static关键字用于修饰类的成员(字段、方法、代码块和内部类),表示它们属于类本身,而不是类的实例。所以static不可以用在类方法论里面。下面四条要记住:
使用static关键字的一些常见用途包括:
- 静态字段(static fields):静态字段是属于类的字段,而不是属于类的实例。它们在类加载时被初始化,并且在整个程序运行期间保持不变。可以通过类名直接访问静态字段,而不需要创建类的实例。
- 静态方法(static methods):静态方法是属于类的方法,而不是属于类的实例。它们可以直接通过类名调用,而不需要创建类的实例。静态方法不能访问非静态的成员变量和方法,只能访问静态的成员变量和方法(这个可以这么理解:静态方法不需要创建对象就可以访问,属于类,非静态方法属于类的实例对象,所以静态方法不能直接访问非静态的,因为对象是类的具体化,静态是类的固有属性)。
- 静态代码块(static blocks):静态代码块是在类加载时执行的一段代码。它们用于初始化静态字段或执行其他静态操作。静态代码块只会执行一次,并且在类加载时按照它们在代码中的顺序执行。
- 静态内部类(static inner classes):静态内部类是定义在类内部的类,但是它是静态的,不依赖于外部类的实例。静态内部类可以直接通过外部类名访问,而不需要创建外部类的实例。
需要注意的是,静态成员属于类本身,而不是类的实例。因此,它们在内存中只有一份拷贝,并且可以被所有实例共享。同时,静态成员的生命周期与类的生命周期相同,即在类加载时初始化,在程序结束时销毁。
- 创建工具类:将一些通用的方法和字段定义为静态的,可以直接通过类名调用,而不需要创建实例。
- 计数器:使用静态字段来记录某个类的实例数量。
- 常量定义:将一些常量定义为静态字段,可以在整个程序中共享使用。
- 单例模式:使用静态方法和静态字段来实现单例模式,确保只有一个实例被创建。
关键字final用于修饰类、方法和变量,具有不同的含义和用法。2.2懒汉式(Lazy Initialization)
final变量可以是基本数据类型,也可以是引用类型。对于基本数据类型的final变量,其值不能被修改。对于引用类型的final变量,其引用不能被修改,但是引用所指向的对象的内容可以被修改。
- final修饰类:当一个类被声明为final时,表示该类不能被继承。这意味着其他类不能扩展或继承该final类。
- final修饰方法:当一个方法被声明为final时,表示该方法不能被子类重写或覆盖。final方法在父类中已经实现了最终的功能,子类不能对其进行修改。
- final修饰变量:当一个变量被声明为final时,表示该变量的值不能被修改。final变量必须在声明时进行初始化,并且一旦初始化后,其值就不能再被修改。
在Java中,final关键字用于声明一个常量,它可以应用于基本数据类型和引用类型。
对于引用类型的final变量,它的引用不能被修改,意味着一旦引用被赋值后,就不能再指向其他对象。这是因为final变量的引用在内存中是不可变的。
然而,虽然引用不能被修改,但是引用所指向的对象的内容可以被修改。这意味着通过final变量的引用,我们可以修改对象的属性或调用对象的方法,只要这些属性或方法不是被声明为final的。
例如,考虑以下代码片段:
final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
sb是一个final变量,它的引用不能被修改。但是,我们可以通过sb引用来修改StringBuilder对象的内容,将" World"追加到字符串中。
总结起来,对于引用类型的final变量,它的引用不能被修改,但是引用所指向的对象的内容可以被修改。这样的设计可以保护引用不被误修改,同时允许对对象的内容进行修改。final变量在多线程环境下具有线程安全的特性,因为它的值不会被修改。复制代码
- public static void main(String[] args) {
- final StringBuilder s = new StringBuilder();
- StringBuilder b = new StringBuilder();
- StringBuilder c = new StringBuilder();
- b = c;
- s = b;
- /**
- * The final local variable s cannot be assigned. It must be blank
- * and not using a compound assignment
- */
- }
总结:
- final修饰类:表示该类不能被继承。
- final修饰方法:表示该方法不能被重写。
- final修饰变量:表示该变量的值不能被修改。
synchronized2.3 双重检查锁(Double-Checked Locking)
synchronized关键字用于修饰方法或代码块,其作用是实现线程的同步,保证多个线程在访问共享资源时的互斥性和可见性。
当一个方法被synchronized修饰时,同一时刻只能有一个线程执行该方法,其他线程需要等待。这样可以避免多个线程同时访问共享资源导致的数据不一致或错误的问题。
具体来说,synchronized修饰方法的作用有以下几点:
需要注意的是,synchronized修饰方法时,锁的粒度是整个方法,即一个线程获取了该方法的锁,其他线程需要等待该线程执行完整个方法才能获取锁。如果方法中只有一小部分代码需要同步,可以考虑使用synchronized代码块来实现更细粒度的锁定。
- 互斥性:当一个线程进入synchronized修饰的方法时,其他线程需要等待,直到该线程执行完毕释放锁。这样可以保证同一时刻只有一个线程执行该方法,避免了多个线程同时修改共享资源导致的数据不一致问题。
- 可见性:synchronized修饰的方法会将修改共享资源的操作立即刷新到主内存中,其他线程可以立即看到最新的值。这样可以保证多个线程之间对共享资源的操作是可见的,避免了数据的脏读、写入和丢失等问题。
volatile2.4 静态内部类(Static Inner Class)
volatile关键字用于修饰变量,用来保证变量的可见性和禁止指令重排序。
需要注意的是,volatile关键字只能保证可见性和禁止指令重排序,并不能保证原子性。如果需要保证原子性,可以使用synchronized关键字或者使用原子类(如AtomicInteger)。
- 可见性:当一个变量被volatile修饰时,任何对该变量的修改都会立即被其他线程可见,即保证了线程之间的通信。这是因为volatile修饰的变量会被存储在主内存中,每次使用前都会从主内存中读取最新的值。
- 禁止指令重排序:在多线程环境下,为了提高性能,编译器和处理器可能会对指令进行重排序。然而,有些指令重排序可能会导致多线程程序出现问题。使用volatile关键字修饰的变量,可以禁止指令重排序,保证了程序的正确性。
总结起来,volatile关键字在多线程编程中起到了重要的作用,可以保证变量的可见性和禁止指令重排序,从而保证了线程之间的正确通信。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |