AAlion

我走得很慢,但我从不后退


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

设计模式-单例模式

发表于 2019-12-28 | 分类于 Java

@TOC
如果明确要求要懒加载(lazy initialization)会倾向于使用静态内部类,如果涉及到反序列化创建对象时会试着使用枚举方式来实现单例。
分类:https://blog.csdn.net/u011595939/article/details/79972371
实例分析线程安全等问题:https://blog.csdn.net/chenchaofuck1/article/details/51702129

二、饿汉模式

1.饿汉模式实现(单例对象立即加载)

  1. • 饿汉式单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题。因此,可以省略synchronized关键字。
  2. • 问题:如果只是加载本类,而不是要调用getInstance(),甚至永远没有调用,则会造成资源浪费!
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class SingletonDemo02 {
    //创建对象
    private static /*final*/ SingletonDemo02 s = new SingletonDemo02();
    private SingletonDemo02() {
    }//私有化构造器
    //获得唯一可用的对象
    public static /*synchronized*/ SingletonDemo02 getInstance() {
    return s;
    }
    }
  3. 测试
    1
    2
    3
    4
    5
    6
    7
    public class Client {
    public static void main(String[] args) {
    SingletonDemo02 s = SingletonDemo02.getInstance();
    SingletonDemo02 s2 = SingletonDemo02.getInstance();
    System.out.println(s==s2); //结果为true
    }
    }

    三、懒汉模式

    1.懒汉模式实现(单例对象延迟加载)

  4. 要点:
    – lazy load! 延迟加载, 懒加载! 真正用的时候才加载!
  5. 问题:
    – 资源利用率高了。但是,每次调用getInstance()方法都要同步,并发效率较低。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class SingletonLazy {
    /** 懒汉模式-多线程环境,但效率不高 */
    //getInstanceB()方法加上同步关键字sychronized保证在多线程环境下我们还是只能得到该类的一个实例
    // 但每次调用getInstanceB()方法时都被synchronized关键字锁住了,会引起线程阻塞,影响程序的性能。
    private static SingletonLazy instance;

    public static synchronized SingletonLazy getInstance() {
    if (instance == null) {
    instance = new SingletonLazy();
    }
    return instance;
    }
    }

四、双重检测实现

  • 这个模式将同步内容下方到if内部,提高了执行的效率
    不必每次获取对象时都进行同步,只有第一次才同步
    创建了以后就没必要了。
  • 问题: 由于编译器优化原因和JVM底层内部模型原因,
    偶尔会出问题。不建议使用。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SingletonLazy {
/**懒汉模式-双重检验锁-线程安全且并行效率高*/
//多线程不影响程序的性能,不让线程每次调用getInstanceC()方法时都加锁,
// 而只是在实例未被创建时再加锁,在加锁处理里面还需要判断一次实例是否已存在。
private static SingletonLazy instance;

public static SingletonLazy getInstance() {
// 先判断实例是否存在,若不存在再对类对象进行加锁处理
if (instance == null) { //Single Checked
synchronized (SingletonLazy.class) {
if (instance == null) { //Double Checked
instance = new SingletonLazy();
}
}
}
return instance;
}
}

五、静态内部类

  • 静态内部类实现方式(也是一种懒加载方式)-懒汉模式
  • 要点:
    – 外部类没有static属性,则不会像饿汉式那样立即加载对象。
    – 只有真正调用getInstance(),才会加载静态内部类。加载类时是线程 安全的。 instance是static final
    类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性.
    – 兼备了并发高效调用和延迟加载的优势!
  • 实现*
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Singleton {
    private static class SingletonClassInstance {
    private static final Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
    return SingletonClassInstance.instance;
    }

    private Singleton() {
    }
    }

六、枚举方式

饿汉模式

  • 问题:
    – 反射可以破解上面几种(不包含枚举式)实现方式!(可以在构造方法中手动抛出异常控制)
    – 反序列化可以破解上面几种((不包含枚举式))实现方式!
    • 可以通过定义readResolve()防止获得不同对象。
    – 反序列化时,如果对象所在类定义了readResolve(),(实际是一种回调),定义返回哪个对象。
  • 优点:
    – 实现简单
    – 枚举本身就是单例模式。由JVM从根本上提供保障!避免通过反射和反序列化的漏洞!
  • 缺点:
    – 无延迟加载
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public enum Singleton {
    /**
    * 定义一个枚举的元素,它就代表了Singleton的一个实例。
    */
    INSTANCE;
    /**
    * 单例可以有自己的操作
    */
    public void singletonOperation() {
    //功能处理
    }
    }

一、单例模式

1.核心作用

保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

2.应用场景

–Windows的Task Manager(任务管理器)就是很典型的单例模式
– 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,每次new一个对象去读取。
– 网站的计数器,一般也是采用单例模式实现,否则难以同步。
– 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
– 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
– Application 也是单例的典型应用(Servlet编程中会涉及到)
– 在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理

3.单例模式的优点

  1. 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
  2. 单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理

    4.常见的五种单例模式实现方式:

  3. 主要:
    • 饿汉式(线程安全,调用效率高。 但是,不能延时加载。)
    • 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
  4. 其他:
    • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
    • 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
    • 枚举单例(线程安全,调用效率高,不能延时加载)

进程间通信(IPC,InterProcessCommunication)

发表于 2019-12-27 | 分类于 Java

1. 概念

进程间通信(IPC,InterProcess Communication):是指在不同进程之间传播或交换信息。

2. 特点:

管道 (使用最简单);信号 (开销最小);共享映射区 (无血缘关系);本地套接字 (最稳定)。

3. 具体

1)无名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2)高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。
3)有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
4)消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5)信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
6)信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
7)共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
8)套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

ref:https://blog.csdn.net/weixin_42205987/article/details/82972767

线程的工作内存

发表于 2019-12-08 | 分类于 Java

1)<JVM虚拟机>:Java线程之间的通信由Java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在,它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
2)解释
解释下上文所说的主内存和本地内存:
首先,JVM将内存组织为主内存和工作内存两个部分。
主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的栈和对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。
①所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共享的。
②每条线程都有自己的工作内存,工作内存中保存的是主存中某些变量的拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。
③线程之间无法直接访问对方的工作内存中的变量,线程间变量的传递均需要通过主内存来完成。

ref:https://www.jianshu.com/p/679ad52eca05

支持向量机(SVM)的优缺点

发表于 2019-04-23 | 分类于 机器学习

SVM的优缺点

优点:

(1)非线性映射是SVM方法的理论基础,SVM利用内积核函数代替向高维空间的非线性映射;

(2)对特征空间划分的最优超平面是SVM的目标,最大化分类边际的思想是SVM方法的核心;

(3)支持向量是SVM的训练结果,在SVM分类决策中起决定作用的是支持向量。

(4)SVM 是一种有坚实理论基础的新颖的小样本学习方法。它基本上不涉及概率测度及大数定律等,因此不同于现有的统计方法。从本质上看,它避开了从归纳到演绎的传统过程,实现了高效的从训练样本到预报样本的“转导推理”,大大简化了通常的分类和回归等问题。

(5)SVM 的最终决策函数只由少数的支持向量所确定,计算的复杂性取决于支持向量的数目,而不是样本空间的维数,这在某种意义上避免了“维数灾难”。

(6)少数支持向量决定了最终结果,这不但可以帮助我们抓住关键样本、“剔除”大量冗余样本,而且注定了该方法不但算法简单,而且具有较好的“鲁棒”性。这种“鲁棒”性主要体现在:

①增、删非支持向量样本对模型没有影响;

②支持向量样本集具有一定的鲁棒性;

③有些成功的应用中,SVM 方法对核的选取不敏感

缺点:

(1) SVM算法对大规模训练样本难以实施

由于SVM是借助二次规划来求解支持向量,而求解二次规划将涉及m阶矩阵的计算(m为样本的个数),当m数目很大时该矩阵的存储和计算将耗费大量的机器内存和运算时间。针对以上问题的主要改进有有J.Platt的SMO算法、T.Joachims的SVM、C.J.C.Burges等的PCGC、张学工的CSVM以及O.L.Mangasarian等的SOR算法

(2) 用SVM解决多分类问题存在困难

经典的支持向量机算法只给出了二类分类的算法,而在数据挖掘的实际应用中,一般要解决多类的分类问题。可以通过多个二类支持向量机的组合来解决。主要有一对多组合模式、一对一组合模式和SVM决策树;再就是通过构造多个分类器的组合来解决。主要原理是克服SVM固有的缺点,结合其他算法的优势,解决多类问题的分类精度。如:与粗集理论结合,形成一种优势互补的多类问题的组合分类器。

线性分类器与非线性分类器的区别以及优缺点

发表于 2019-04-23 | 分类于 机器学习

• 定义:只考虑二类的情形,所谓线性分类器即用一个超平面将正负样本分离开,表达式为 y=wx 。这里是强调的是平面。而非线性的分类界面没有这个限制,可以是曲面,多个超平面的组合等。【如果模型是参数的线性函数,并且存在线性分类面,那么就是线性分类器,否则不是。SVM两种都有(看线性核还是高斯核)。】

• 在线性分类器的基础上,用分段线性分类器可以实现更复杂的分类面。

非线性判别函数解决比较复杂的线性不可分样本分类问题,解决问题比较简便的方法是采用多个线性分界面将它们分段连接,用分段线性判别划分去逼近分界的超曲面。

• 常见的线性分类器有:LR,贝叶斯分类,单层感知机、线性回归。

优缺点:算法简单和具有“学习”能力。线性分类器速度快、编程方便,但是可能拟合效 果不会很好。

• 常见的非线性分类器:决策树、RF、GBDT、多层感知机。

优缺点:非线性分类器编程复杂,但是效果拟合能力强。

Leetcode 2: Add Two Numbers

发表于 2018-09-25 | 分类于 算法

难度:Medium

题目描述

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

阅读全文 »

线性分类器与非线性分类器的区别以及优缺点

发表于 2018-09-20 | 分类于 机器学习

• 定义:只考虑二类的情形,所谓线性分类器即用一个超平面将正负样本分离开,表达式为 y=wx 。这里是强调的是平面。而非线性的分类界面没有这个限制,可以是曲面,多个超平面的组合等。【如果模型是参数的线性函数,并且存在线性分类面,那么就是线性分类器,否则不是。SVM两种都有(看线性核还是高斯核)。】

• 在线性分类器的基础上,用分段线性分类器可以实现更复杂的分类面。

非线性判别函数解决比较复杂的线性不可分样本分类问题,解决问题比较简便的方法是采用多个线性分界面将它们分段连接,用分段线性判别划分去逼近分界的超曲面。

• 常见的线性分类器有:LR,贝叶斯分类,单层感知机、线性回归。

优缺点:算法简单和具有“学习”能力。线性分类器速度快、编程方便,但是可能拟合效 果不会很好。

• 常见的非线性分类器:决策树、RF、GBDT、多层感知机。

优缺点:非线性分类器编程复杂,但是效果拟合能力强。

Leetcode 39: Combination Sum

发表于 2018-09-05 | 分类于 算法

难度:medium

题目描述

给定一个无重复元素的数组candidates和一个目标数target ,找出candidates中所有可以使数字和为target的组合。
candidates中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。
    阅读全文 »

Leetcode 56: Merge Intervals

发表于 2018-08-24 | 分类于 算法

难度:Medium

题目描述

给出一个区间的集合,请合并所有重叠的区间。

示例

示例1

1
2
3
输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
阅读全文 »

Leetcode 313: Super Ugly Number

发表于 2018-08-22 | 分类于 算法

难度:Medium
相似题目:

  • 264. Ugly Number II

题目描述

编写一段程序来查找第n个超级丑数。
超级丑数是指其所有质因数都是长度为k的质数列表primes中的正整数。

阅读全文 »
<i class="fa fa-angle-left"></i>123<i class="fa fa-angle-right"></i>

AAlion

Happy Code, Happy Life

22 日志
5 分类
26 标签
© 2021 AAlion
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4