前言:
大家好,我是良辰丫,今天我们来学习一下单例模式,这是一道经典面试题,我们一起瞧一下单例模式.💞💞💞
🧑个人主页:良辰针不戳
📖所属专栏:javaEE初阶
🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
💦期待大家三连,关注,点赞,收藏。
💌作者能力有限,可能也会出错,欢迎大家指正。
💞愿与君为伴,共探Java汪洋大海。

单例模式
所谓
单例模式,是一种经典的设计模式,设计模式有很多种,单例模式只是其中的一种.
我们可以把设计模式想象成一套棋谱(一些高手总结出来的下棋策略),按照套路写代码,总比自己脑子空想要好得多.
单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例.
我们饿的时候就去吃饭,此时饭早已经做好了,这就是对于饿汉模式的描述;打开一个很大的文件夹,饿汉模式是把所有的内容都读到内存中并显示.
我们来进行书写饿汉模式的代码,再次强调单例模式只能有一个对象,饿汉模式提前就new好了自己的对象.
//单例模式中的饿汉模式
class Singleton{
//1.使用static创建一个实例,并且进行实例化
//这个instance对应的实例,是该类的唯一实例
//在类内部把实例创建好,禁止外部重新创建实例(保证单例特性)
private static Singleton instance = new Singleton();
//2. 为了防止不能再次new(构造方法)
private Singleton(){
}
//3. 提供一个方法,让外界能够拿到唯一的实例
public static Singleton getInstance(){
return instance;
}
}
public class Test34 {
public static void main(String[] args) {
//下面的两个实例是同一个对象
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2);
//下面就不能进行new操作
//Singleton s = new Singleton();
}
}
被static修饰的属性为类属性,JVM中每个类对象只有唯一的一份,类对象里的成员也是唯一的一份.

说到懒汉模式并不是真的懒,饿了但是没到饭点,忙完手头的工作,再去做饭(此时饭还没有做好);打开一个比较大的文件,懒汉模式一小部分一小部分的读文件,把当前屏幕填充上,如果用户翻页了,再读其它页面内容.
在饿汉模式下,读取较大文件可能会卡半天,面临内存不够的情况;但是在懒汉模式下可以快速的打开文件,并且进行浏览.
关于懒汉模式的代码,用的时候再进行new对象.
import java.util.Timer;
import java.util.TimerTask;
//懒汉模式实现单例模式
class SingLazy{
//1.用的时候再创建(非必要不创建)
volatile private static SingLazy singLazy = null;
//2.禁止new
private SingLazy(){}
//3.获取返回
public static SingLazy getInstance(){
synchronized (SingLazy.class){
if(singLazy ==null){
if(singLazy == null){
singLazy = new SingLazy();
}
}
}
return singLazy;
}
}
public class Test35 {
public static void main(String[] args) {
SingLazy s = SingLazy.getInstance();
SingLazy s2 = SingLazy.getInstance();
System.out.println(s == s2);
}
}

饿汉模式只是读数据,认为线程是安全的;但是懒汉模式涉及到读数据和改数据,多线程下改数据(进行new对象)可能无法保证创建对象的唯一性.
多new几个对象又有什么问题呢?不是有问题,是有大问题,在以后,我们可能会遇到内存管理对象很大的内存,一个对象几百消耗G内存,多new几次会把服务器搞奔溃.那么我们如何解决线程安全问题呢?
==加锁可能会极大的减少上述问题 .==保证new是一个原子操作.

注意:
加锁其实是一个非常低效的操作,加锁可能会涉及到阻塞等待,因此我们需要了解,非必要不加锁.
上述代码中有两个if语句,if中的条件一样,那么为什么要写两次呢?注意我们处理的是多线程,多线程的调度具有随机性,谁也不知道执行完一个if语句后会发生怎样的情况.
即使加锁以后,也会出现问题,两个线程同时调用实例对象,但是这种可能性很小.
单例模式存在线程安全问题.
- 饿汉模式,只是读操作,本来就是安全的.
- 懒汉模式,涉及到读写操作,是不安全的.
如何解决单例模式线程安全.
- 加锁,把if和new变成原子操作.
- 双重if,减少不必要的加锁操作.
- 使用volatile,禁止指令重排序,保证后序线程肯定拿到的是完整的对象.
后序:
单例模式的讲解就到这里了,希望小小的文章可以帮到大家,我们下一篇文章再见.💟💟💟
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?
我是ruby的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp
了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl
我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它: