单例设计模式,各种排序复习

1.单例设计模式

资料来源

1.1单例模式是什么?

单例模式,属于创建类型的一种常用的软件设计模式

通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)。就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。

1.2单例模式使用的场景:

复制代码
需要频繁的进行创建和销毁的对象

创建对象时耗时过多或耗费资源过多(重量级对象)

经常用到的对象、工具类对象、频繁访问数据库或文件的对象(数据源、session工厂)

1.3饿汉式

所谓饿汉式,就是直接创建出类的实例化,然后用private私有化,对外只用静态方法暴露。

静态变量(可用)

步骤

复制代码
构造器私有化
类的内部创建对象
向外暴露一个静态的公共方法
优点 缺点
写法简单,在类装载的时完成实例化,避免了线程同步问题 类装载时完成实例化,没有达到LazyLoading的效果,若该实例从未使用,则会造成内存浪费
java 复制代码
class Singleton {
	//私有化构造器
	private Singleton() {	
	}
	//内部创建对象实例
	private final static Singleton instance = new Singleton();
	//对外公有的静态方法
	public static Singleton getInstance() {
		return instance;
	}
}

静态代码块(可用)

将类的实例化放到静态代码块中的写法,基本同上。

java 复制代码
class Singleton {  //静态代码块
	//私有化构造器
	private Singleton() {}
	//内部创建对象实例
	private  static Singleton instance;
	static { // 在静态代码块中,创建单例对象
		instance = new Singleton();
	}
	//对外公有的静态方法
	public static Singleton getInstance() {
		return instance;
	}
}

测试代码

java 复制代码
public static void main(String[] args) {
		Singleton instance1 = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance1 == instance2);
		System.out.println("instance1.hashCode=" + instance1.hashCode());
		System.out.println("instance2.hashCode=" + instance2.hashCode());
	}

1.4懒汉式

所谓懒汉式,就是在需要调用的时候再创建类的实例化。

线程不安全 (不推荐)

起到了懒加载效果,但是只能在单线程使用,多线程会不安全,因为当多个线程并发同时判断instance为空时,就会相应的实例化多个对象。

java 复制代码
class Singleton {
    //线程不安全
    private static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {  
    //调用时才实例化对象,懒汉式
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

线程安全 (不推荐)

上面线程不安全,那上锁不就好了,使用synchronized关键字。

这样虽然解决了线程安全,但其实实例化操作只做一次,而获取实例(即getInstance)的操作是很多次的,把调用的方法加上同步,会大大降低效率。

java 复制代码
class Singleton { //线程安全
    private static Singleton instance;
    private Singleton() {}
    //synchronized同步处理
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

1.5 双重检查 *****最重要的一种

上面代码效率低,那在同步前判断一下有没有实例化不就好了,

若没有实例化则用同步方法new一个,否则直接return即可。即所谓的双重检查。

需要用到关键字volatile,防止指令重排。如果不用volatile关键字,就会和线程不安全情形一样,在if判断那会有并发。

java 复制代码
class Singleton { 

	//双重检查
	private static volatile Singleton instance;
	private Singleton() {}
	public static synchronized Singleton getInstance() {
		if(instance == null) {
		 //判断是否实例化
			synchronized (Singleton.class) {
				if(instance == null) {
					instance = new Singleton();
				}
			}
		}
		return instance; //否则直接return
	}
}

这样既实现了懒加载,又保证了线程安全。

1.6静态内部类

静态内部类在外部类装载时不会实例化,当调用的时候才会装载并实例化,且JVM保证了其装载时的线程安全性。也能保证懒加载和线程安全,有点像自带版的双重检查。

java 复制代码
class Singleton {
	private static volatile Singleton instance;
	private Singleton() {}
	//静态内部类,包含一个静态属性:Singleton
	private static class SingletonInstance {
		private static final Singleton INSTANCE = new Singleton(); 
	}
	//对外公有的静态方法,直接返回SingletonInstance.INSTANCE
	public static synchronized Singleton getInstance() {
		return SingletonInstance.INSTANCE;
	}
}

1.7枚举

其实,使用枚举也能实现单例模式,不仅能避免多线程同步问题,也能防止反序列化重新创建新的对象。

java 复制代码
enum Singleton {
	INSTANCE; //属性
	public void say() {
		System.out.println("记得三连~");
	}
}

2.排序


3.冒泡排序

复制代码
算法步骤
  1. 比较相邻的元素,如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的比价,从开始第一对到结尾的最后一对,这样在最后的元素就是最大的数;
  3. 针对所有的元素重复以上的步骤,除了数组最后已经排好序的数组;
  4. 重复步骤1~3,直到排序完成。
java 复制代码
public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++) {
            boolean flag = true;
            for (int j = 0; j < len - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = false;
                }
            }
            if (flag) {
                break;
            }
        }
    }
}

4.选择排序(Selection Sort)

复制代码
算法步驟
  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置;
  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
  3. 重复第2步,直到所有元素均排序完毕。
java 复制代码
public class SelectionSort {
    public static void selectionSort(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++)
         {
            int minVal = i;
            //确定本轮最小的数字的定位
            for (int j = i + 1; j < len; j++) {
                if (arr[minVal] > arr[j]) {
                    minVal = j;
                     }
                }
             //进行一次选择---选到最小的数字
            if (minVal != i) {
                int tmp = arr[i];
                arr[i] = arr[minVal];
                arr[minVal] = tmp;
            }
        }
    }
}

5.快速排序(Quick Sort)

算法步驟

  1. 从序列中随机挑出一个元素,做为基准(pivot,这里选择序列的最左边元素作为基准);
  2. 重新排列序列,将所有比基准值小的元素摆放在基准前面,所有比基准值大的摆在基准的后面。该操作结束之后,该基准就处于数列的中间位置。这个操作称为分区(partition);
  3. 递归地把小于基准值元素的子序列和大于基准值元素的子序列进行上述操作即可。

java 复制代码
public class QuickSort {
    public static void quickSort(int[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    private static void sort(int[] arr, int left, int right) {
        if (left < right) {
            int pivotIdx = partition(arr, left, right);
            sort(arr, 0, pivotIdx - 1);
            sort(arr, pivotIdx + 1, right);
        }
    }

    private static int partition(int[] arr, int left, int right) {
        int idx = left + 1;
        for (int i = idx; i <= right; i++) {
            if (arr[left] > arr[i]) {
                swap(arr, i, idx++);
            }
        }
        swap(arr, left, idx - 1);
        return idx - 1;
    }

    private static void swap(int[] arr, int idx1, int idx2) {
        int tmp = arr[idx1];
        arr[idx1] = arr[idx2];
        arr[idx2] = tmp;
    }
}
相关推荐
晨米酱19 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤1 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤2 天前
工厂模式
设计模式