1. 首页
  2. 网络编程教程

009-九、网络编程之多线程之单例模式

引言

java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。
单例模式有以下特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其它对象提供这一实例。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。

目录

  1. 饿汉式单例
  2. 懒汉式单例
  3. 静态嵌套类单例
    4.static代码块单例

饿汉式

饿汉模式的意思就是使用该类时候就已经将该实例创建完毕了,看看饿汉式的代码


/** * 饿汉式 */ public class SingleTest { /** * 立即加载===饿汉模式 */ private static SingleTest singleTest = new SingleTest(); private SingleTest(){} public static SingleTest getInstance(){ return singleTest; } } class Test { public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { //为了演示效果这里加上延时2秒 try { Thread.sleep(2000); System.out.println(SingleTest.getInstance().hashCode()); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread thread1 = new Thread(runnable); Thread thread2 = new Thread(runnable); Thread thread3 = new Thread(runnable); Thread thread4 = new Thread(runnable); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } } 结果:

以上使用了四个线程执行了 SingleTest 类的实例。,打印出来的 hashcode 都是一致的表示都是同一实例。

懒汉式

懒汉式实际上就是延时加载,延时加载意思就是在调用 getInstance 的方法时才被创建实例。
但是懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个 SingleTest 实例,要实现线程安全,有以下三种方式,都是对 getInstance 这个方法改造,保证了懒汉式单例的线程安全,如果你第一次接触单例模式,对线程安全不是很了解,可以先跳过下面这三小条,去看饿汉式单例,等看完后面再回头考虑线程安全的问题。
1.改造成员变量


private static SingleTest singleTest = new SingleTest(); 改为: private static SingleTest singleTest;

2.改造getInstance方法


/** * 饿汉式 */ public class SingleTest { /** * 立即加载===饿汉模式 */ private static SingleTest singleTest; private SingleTest(){} public static SingleTest getInstance() throws InterruptedException { if (singleTest == null) { //为了演示效果 Thread.sleep(3000); singleTest = new SingleTest(); } return singleTest; } } //结果

这样输出就出现了不同的实例,那么该怎么解决这个问题呢,这个时候就需要增加同步操作了!
继续改造 getInstance 方法,只需要加上同步锁关键字 synchronized


public synchronized static SingleTest getInstance() throws InterruptedException { if (singleTest == null) { //为了演示效果 Thread.sleep(3000); singleTest = new SingleTest(); } return singleTest; } 运行结果

这样就实现了单例了,但是这样的效率非常低,因为每次进入该方法都需要拿到同步锁才能执行代码块,所以需要使用代码块方法来改造。


public static SingleTest getInstance() throws InterruptedException { if (singleTest == null) { //为了演示效果 Thread.sleep(3000); synchronized (SingleTest.class) { /** * 每次进入同步块之后还需要再次判断下singleTest是否为空 * 因为在这个同步代码块的区域singleTest在线程下当第二个线程拿到锁之后 * 这个时候singleTest已经不为空了所以就不需要在实例化了这个时候就需要判断一下 * 所以需要判断一下,不过大家可以测试一下 */ if (singleTest == null) { singleTest = new SingleTest(); } } } return singleTest; } 运行结果:

以上就是多线程下的单例模式的最常用使用方法,注释也写上去了!!!

静态嵌套类单例

直接就上代码了,单例基本上都是差不多的,只是变了一种形式展现!!!


/** * 饿汉式 */ public class SingleTest { /** * 内部嵌套类实现单例 */ public static class MySingleTest { /** * 立即加载===饿汉模式 */ private static SingleTest singleTest = new SingleTest(); } private SingleTest(){} public static SingleTest getInstance() throws InterruptedException { return MySingleTest.singleTest; } } class Test { public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(SingleTest.getInstance().hashCode()); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread thread1 = new Thread(runnable); Thread thread2 = new Thread(runnable); Thread thread3 = new Thread(runnable); thread1.start(); thread2.start(); thread3.start(); } } 结果

以上就是个简单的内部嵌套类的单例模式!!!

static代码块单例模式

也很简单,看代码吧!!!


/** * 饿汉式 */ public class SingleTest { /** * 立即加载===饿汉模式 */ private static SingleTest singleTest; private SingleTest(){} /** * 代码块单例 */ static{ singleTest = new SingleTest(); } /** * 获取实例的方法 * @return */ public static SingleTest getInstance() { return singleTest; } } class Test { public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(SingleTest.getInstance().hashCode()); } } }; Thread thread1 = new Thread(runnable); Thread thread2 = new Thread(runnable); Thread thread3 = new Thread(runnable); thread1.start(); thread2.start(); thread3.start(); } } 运行结果:

写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
  4. JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

    本文著作权归作者所有,如若转载,请注明出处

    转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

    标题:009-九、网络编程之多线程之单例模式

    链接:https://www.javajike.com/article/1232.html

« 010-十、网络编程多线程之线程池
008-八、网络编程之多线程之管道流»

相关推荐

QR code