싱글톤 패턴과 자바의 싱글톤
머리말
이 글은 제 공식 계정에서 가져온 것입니다. 못 보신 분들은 다시 읽어보셔도 좋습니다. 오늘 설명드린 내용을 약간 수정했습니다. 는 다음과 같습니다 :
1. 싱글턴 패턴이란
【Singleton Pattern】, 영문명 : Singleton Pattern, 이 패턴은 매우 간단하며, 인스턴스가 하나만 필요한 유형입니다. 유형 소프트웨어 디자인 패턴을 만드는 방법. 싱글톤 모드 메서드를 통해 생성된 클래스는 현재 프로세스에 인스턴스가 하나만 있습니다(필요한 경우 스레드의 싱글톤일 수도 있습니다. 예를 들어 스레드 컨텍스트 내에서는 동일한 인스턴스만 사용됩니다).
(추천 동영상: java 동영상 튜토리얼)
1. 싱글톤 클래스는 하나의 인스턴스만 가질 수 있습니다.
2. 싱글톤 클래스는 고유한 인스턴스를 생성해야 합니다.
3. 싱글톤 클래스는 이 인스턴스를 다른 모든 개체에 제공해야 합니다.
그렇다면 솔직히 말하면 전체 프로젝트 주기 동안 인스턴스가 하나만 존재하게 되며, 인스턴스가 다시 시작되면 인스턴스가 다시 생성됩니다. .
위에서 명사 [창작형]의 디자인 패턴을 언급했는데, 창작형의 디자인 패턴은 무엇인가요?
Creational 패턴: 객체 생성을 담당합니다. 이 패턴을 사용하여 필요한 객체 인스턴스를 생성합니다.
생성 패턴 외에도 두 가지 다른 유형의 패턴이 있습니다.
구조적 패턴: 클래스와 객체 간의 조합을 처리합니다.
행동 패턴: 클래스와 객체 간의 상호 작용에서 책임의 분할을 처리합니다.
이 두 가지 디자인 패턴은 앞으로 천천히 논의될 예정이지만 지금은 여기에 나열되지 않습니다.
싱글톤 모드에서 0부터 시작하여 객체 인스턴스를 생성하는 방법을 중점적으로 분석해 보겠습니다.
2. 싱글턴 모드를 만드는 방법
싱글턴 모드를 구현하는 방법에는 여러 가지가 있습니다: "게으른 남자 스타일"에서 "배고픈 남자 스타일", 그리고 마지막으로 "이중 확인 잠금" 모드까지, 여기에서는 천천히 살펴보겠습니다. , 싱글톤을 만드는 방법에 대한 단계별 가이드부터 시작하세요.
1. 일반적인 논리적 사고 순서
단일 인스턴스를 생성하려면 먼저 인스턴스를 생성하는 방법을 배워야 합니다. 이는 매우 간단합니다.
/// <summary> /// 定义一个天气类 /// </summary> public class WeatherForecast { public WeatherForecast() { Date = DateTime.Now; } public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } } [HttpGet] public WeatherForecast Get() { // 实例化一个对象实例 WeatherForecast weather = new WeatherForecast(); return weather; }
우리는 여러분이 방문할 때마다 시간이 바뀌기 때문에 인스턴스가 항상 생성되고 변경됩니다.
이 코드가 무엇을 의미하는지 모두가 알 수 있다고 믿습니다. 많은 말은 하지 않겠습니다. 바로 아래에서 우리는 싱글톤 모드의 핵심 목적이 다음과 같다는 것을 알고 있습니다.
이 인스턴스는 전체 시스템 실행 주기 동안 고유해야 중간에 문제가 발생하지 않도록 해야 합니다.
그럼 우리만 발전하고 싶다고 하지 않았나요? 그냥 직접 반환할 수 있나요?
/// <summary> /// 定义一个天气类 /// </summary> public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义私有构造函数,使外界不能创建该类实例 private WeatherForecast() { Date = DateTime.Now; } /// <summary> /// 静态方法,来返回唯一实例 /// 如果存在,则返回 /// </summary> /// <returns></returns> public static WeatherForecast GetInstance() { // 如果类的实例不存在则创建,否则直接返回 // 其实严格意义上来说,这个不属于【单例】 if (uniqueInstance == null) { uniqueInstance = new WeatherForecast(); } return uniqueInstance; } public DateTime Date { get; set; }public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } }
그런 다음 기본 생성자가 사유화되었고 더 이상 인스턴스 생성이 허용되지 않기 때문에 호출 메서드를 수정합니다. 따라서 직접 호출합니다.
[HttpGet] public WeatherForecast Get() { // 实例化一个对象实例 WeatherForecast weather = WeatherForecast.GetInstance(); return weather; }
마지막으로 효과를 살펴보겠습니다.
이때 시간이 변하지 않은 것을 볼 수 있는데 이는 우리의 인스턴스가 고유하고 끝났다는 것을 의미합니다! 정말 행복하지 않나요!
하지만 걱정하지 마십시오. 현재 단일 스레드이므로 하나만 있습니다. 여러 스레드가 동시에 액세스하면 정상입니까?
여기서 테스트를 합니다. 프로젝트를 시작할 때 멀티스레딩을 사용하여 다음을 호출합니다.
[HttpGet] public WeatherForecast Get() { // 实例化一个对象实例 //WeatherForecast weather = WeatherForecast.GetInstance(); // 多线程去调用 for (int i = 0; i < 3; i++) { var th = new Thread( new ParameterizedThreadStart((state) => { WeatherForecast.GetInstance(); }) ); th.Start(i); } return null; }
그런 다음 생성자를 한 번만 통과하면 효과가 무엇인지 살펴보겠습니다. 아님:
3个线程在第一次访问GetInstance方法时,同时判断(uniqueInstance ==null)这个条件时都返回真,然后都去创建了实例,这个肯定是不对的。那怎么办呢,只要让GetInstance方法只运行一个线程运行就好了,我们可以加一个锁来控制他,代码如下:
public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义一个锁,防止多线程 private static readonly object locker = new object(); // 定义私有构造函数,使外界不能创建该类实例 private WeatherForecast() { Date = DateTime.Now; } /// <summary> /// 静态方法,来返回唯一实例 /// 如果存在,则返回 /// </summary> /// <returns></returns> public static WeatherForecast GetInstance() { // 当第一个线程执行的时候,会对locker对象 "加锁", // 当其他线程执行的时候,会等待 locker 执行完解锁 lock (locker) { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new WeatherForecast(); } } return uniqueInstance; } public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } }
这个时候,我们再并发测试,发现已经都一样了,这样就达到了我们想要的效果,但是这样真的是最完美的么,其实不是的,因为我们加锁,只是第一次判断是否为空,如果创建好了以后,以后就不用去管这个 lock 锁了,我们只关心的是 uniqueInstance 是否为空,那我们再完善一下:
/// <summary> /// 定义一个天气类 /// </summary> public class WeatherForecast { // 定义一个静态变量来保存类的唯一实例 private static WeatherForecast uniqueInstance; // 定义一个锁,防止多线程 private static readonly object locker = new object(); // 定义私有构造函数,使外界不能创建该类实例 private WeatherForecast() { Date = DateTime.Now; } /// <summary> /// 静态方法,来返回唯一实例 /// 如果存在,则返回 /// </summary> /// <returns></returns> public static WeatherForecast GetInstance() { // 当第一个线程执行的时候,会对locker对象 "加锁", // 当其他线程执行的时候,会等待 locker 执行完解锁 if (uniqueInstance == null) { lock (locker) { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new WeatherForecast(); } } } return uniqueInstance; } public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } }
这样才最终的完美实现我们的单例模式!搞定。
2、幽灵事件:指令重排
当然,如果你看完了上边的那四步已经可以出师了,平时我们就是这么使用的,也是这么想的,但是真的就是万无一失么,有一个 JAVA 的朋友提出了这个问题,C# 中我没有听说过,是我孤陋寡闻了么:
单例模式的幽灵事件,时令重排会偶尔导致单例模式失效。
是不是听起来感觉很高大上,而不知所云,没关系,咱们平时用不到,但是可以了解了解:
为何要指令重排?
指令重排是指的 volatile,现在的CPU一般采用流水线来执行指令。一个指令的执行被分成:取指、译码、访存、执行、写回、等若干个阶段。然后,多条指令可以同时存在于流水线中,同时被执行。
指令流水线并不是串行的,并不会因为一个耗时很长的指令在“执行”阶段呆很长时间,而导致后续的指令都卡在“执行”之前的阶段上。
相反,流水线是并行的,多个指令可以同时处于同一个阶段,只要CPU内部相应的处理部件未被占满即可。比如说CPU有一个加法器和一个除法器,那么一条加法指令和一条除法指令就可能同时处于“执行”阶段, 而两条加法指令在“执行”阶段就只能串行工作。
相比于串行+阻塞的方式,流水线像这样并行的工作,效率是非常高的。
然而,这样一来,乱序可能就产生了。比如一条加法指令原本出现在一条除法指令的后面,但是由于除法的执行时间很长,在它执行完之前,加法可能先执行完了。再比如两条访存指令,可能由于第二条指令命中了cache而导致它先于第一条指令完成。
一般情况下,指令乱序并不是CPU在执行指令之前刻意去调整顺序。CPU总是顺序的去内存里面取指令,然后将其顺序的放入指令流水线。但是指令执行时的各种条件,指令与指令之间的相互影响,可能导致顺序放入流水线的指令,最终乱序执行完成。这就是所谓的“顺序流入,乱序流出”。
这个是从网上摘录的,大概意思看看就行,理解双检锁失效原因有两个重点
1、编译器的写操作重排问题.
例 : B b = new B();
上面这一句并不是原子性的操作,一部分是new一个B对象,一部分是将new出来的对象赋值给b.
直觉来说我们可能认为是先构造对象再赋值.但是很遗憾,这个顺序并不是固定的.再编译器的重排作用下,可能会出现先赋值再构造对象的情况.
2、结合上下文,结合使用情景.
理解了1中的写操作重排以后,我卡住了一下.因为我真不知道这种重排到底会带来什么影响.实际上是因为我看代码看的不够仔细,没有意识到使用场景.双检锁的一种常见使用场景就是在单例模式下初始化一个单例并返回,然后调用初始化方法的方法体内使用初始化完成的单例对象.
三、Singleton = 单例 ?
上边我们说了很多,也介绍了很多单例的原理和步骤,那这里问题来了,我们在学习依赖注入的时候,用到的 Singleton 的单例注入,是不是和上边说的一回事儿呢,这里咱们直接多多线程测试一下就行:
/// <summary> /// 定义一个心情类 /// </summary> public class Feeling { public Feeling() { Date = DateTime.Now; } public DateTime Date { get; set; } } // 单例注册到容器内 services.AddSingleton<Feeling>();
这里重点表扬下评论区的@我是你帅哥 小伙伴,及时的发现了我文章的漏洞,笔芯!
紧接着我们就控制器注入服务,然后多线程测试:
private readonly ILogger<WeatherForecastController> _logger; private readonly Feeling _feeling; public WeatherForecastController(ILogger<WeatherForecastController> logger, Feeling feeling) { _logger = logger; _feeling = feeling; } [HttpGet] public WeatherForecast Get() { // 实例化一个对象实例 //WeatherForecast weather = WeatherForecast.GetInstance(); // 多线程去调用 for (int i = 0; i < 3; i++) { var th = new Thread( new ParameterizedThreadStart((state) => { //WeatherForecast.GetInstance(); // 此刻的心情 Console.WriteLine(_feeling.Date); }) ); th.Start(i); } return null; }
测试的结果,情理之中,只在我们项目初始化服务的时候,进入了一次构造函数:
위에서 말한 것과 같습니다. Singleton은 일종의 싱글턴이고 이중 확인 잠금이기도 합니다. 왜냐하면 싱글턴 모드를 사용할 때 Sigleton을 직접 종속성 주입으로 사용할 수 있다는 결론을 내릴 수 있기 때문입니다. 매우 편리합니다.
4. 싱글톤 패턴의 장점과 단점
【우수함】싱글톤 패턴의 장점:
(1) 고유성 보장: 다른 객체의 인스턴스화를 방지하고 인스턴스의 고유성을 보장합니다.
(2) ) , 전역성: 데이터를 정의한 후 전체 프로젝트 내 어디에서나 현재 인스턴스 및 데이터를 사용할 수 있습니다.
[열등], 싱글톤 모드의 단점:
(1), 메모리 상주: 싱글톤의 수명이 가장 길기 때문에; 데이터가 계속 추가되거나 상주하게 되면 일정량의 메모리 소모가 발생하게 됩니다.
다음 내용은 Baidu Encyclopedia에서 가져온 것입니다.
Advantages
1. 인스턴스 제어
싱글톤 모드는 다른 개체가 자신의 싱글톤 개체 복사본을 인스턴스화하는 것을 방지하여 모든 개체가 고유한 인스턴스에 액세스하도록 합니다.
2. 유연성
클래스가 인스턴스화 프로세스를 제어하므로 클래스는 인스턴스화 프로세스를 유연하게 변경할 수 있습니다.
단점
1. 오버헤드
양은 적지만 객체가 참조를 요청할 때마다 클래스의 인스턴스가 존재하는지 확인하면 약간의 오버헤드가 필요합니다. 이 문제는 정적 초기화를 사용하여 해결할 수 있습니다.
2. 개발 혼란 가능성
싱글톤 개체(특히 클래스 라이브러리에 정의된 개체)를 사용할 때 개발자는 new 키워드를 사용하여 개체를 인스턴스화할 수 없다는 점을 기억해야 합니다. 라이브러리 소스 코드에 액세스할 수 없기 때문에 응용 프로그램 개발자는 예기치 않게 이 클래스를 직접 인스턴스화하지 못할 수도 있습니다.
3. 개체 수명
은 단일 개체 삭제 문제를 해결할 수 없습니다. 메모리 관리를 제공하는 언어(예: .NET Framework 기반 언어)에서는 인스턴스에 대한 전용 참조가 포함되어 있기 때문에 싱글톤 클래스만 인스턴스 할당을 취소할 수 있습니다. 일부 언어(예: C++)에서는 다른 클래스가 개체 인스턴스를 삭제할 수 있지만 이로 인해 싱글톤 클래스에 매달린 참조가 발생합니다.
이 기사는 PHP 중국어 웹사이트, java tutorial 칼럼에서 가져온 것입니다. 학습을 환영합니다!
위 내용은 싱글톤 패턴과 자바의 싱글톤의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











JS 싱글톤 패턴은 클래스에 인스턴스가 하나만 있도록 보장하는 일반적으로 사용되는 디자인 패턴입니다. 이 모드는 이름 충돌과 반복적인 로딩을 방지하기 위해 전역 변수를 관리하는 데 주로 사용됩니다. 또한 메모리 사용량을 줄이고 코드 유지 관리성과 확장성을 향상시킬 수 있습니다.

싱글톤 패턴: 함수 오버로딩을 통해 다양한 매개변수를 갖는 싱글톤 인스턴스를 제공합니다. 팩토리 패턴: 기능 재작성을 통해 다양한 유형의 객체를 생성하여 특정 제품 클래스에서 생성 프로세스를 분리합니다.

소프트웨어 개발에서 우리는 여러 개체가 동일한 리소스에 액세스해야 하는 상황에 자주 직면합니다. 리소스 충돌을 방지하고 프로그램 효율성을 향상시키기 위해 디자인 패턴을 사용할 수 있습니다. 그중 싱글톤 패턴은 객체를 생성하는 데 일반적으로 사용되는 방법으로, 클래스에 인스턴스가 하나만 있도록 보장하고 전역 액세스를 제공합니다. 이 기사에서는 PHP를 사용하여 싱글톤 패턴을 구현하는 방법을 소개하고 몇 가지 모범 사례 제안을 제공합니다. 1. 싱글턴 모드란 무엇입니까? 싱글턴 모드는 객체를 생성하는 데 일반적으로 사용되는 방법으로, 클래스에 인스턴스가 하나만 있도록 보장하고 제공하는 것이 특징입니다.

싱글톤 패턴은 클래스에 인스턴스가 하나만 있고 전역 액세스 지점을 제공하도록 보장합니다. 이는 애플리케이션에서 하나의 객체만 사용 가능하고 제어되도록 보장합니다. 싱글톤 패턴은 클래스의 개체를 인스턴스화하지 않고 고유한 개체에 직접 액세스하는 방법을 제공합니다. 예<php classdatabase{ publicstatic$connection;

소개 PHP 디자인 패턴은 소프트웨어 개발의 일반적인 과제에 대한 입증된 솔루션 세트입니다. 이러한 패턴을 따르면 개발자는 우아하고 강력하며 유지 관리가 가능한 코드를 만들 수 있습니다. 이는 개발자가 SOLID 원칙(단일 책임, 개방형 폐쇄형, Liskov 대체, 인터페이스 격리 및 종속성 반전)을 따르도록 지원하여 코드 가독성, 유지 관리성 및 확장성을 향상시킵니다. 디자인 패턴의 유형 다양한 디자인 패턴이 있으며 각각 고유한 목적과 장점을 가지고 있습니다. 다음은 가장 일반적으로 사용되는 PHP 디자인 패턴 중 일부입니다. 싱글톤 패턴: 클래스에 인스턴스가 하나만 있는지 확인하고 이 인스턴스에 전역적으로 액세스할 수 있는 방법을 제공합니다. 팩토리 패턴: 정확한 클래스를 지정하지 않고 객체를 생성합니다. 개발자는 조건부로

PHP 분산 시스템에서 싱글톤 모드의 애플리케이션 시나리오 및 스레드 안전 프로세스 소개: 인터넷의 급속한 발전으로 분산 시스템은 현대 소프트웨어 개발에서 뜨거운 주제가 되었습니다. 분산 시스템에서 스레드 안전성은 항상 중요한 문제였습니다. PHP 개발에서 싱글톤 패턴은 일반적으로 사용되는 디자인 패턴으로 리소스 공유 및 스레드 안전 문제를 효과적으로 해결할 수 있습니다. 이 기사에서는 PHP 분산 시스템에서 싱글톤 패턴의 애플리케이션 시나리오 및 스레드 안전 프로세스에 중점을 두고 특정 코드 예제를 제공합니다. 1. 싱글톤 모드

1. PHP 디자인 패턴이란 무엇입니까? PHP 디자인 패턴은 일반적인 소프트웨어 개발 문제를 해결하도록 설계된 사전 정의된 코드 템플릿입니다. 코드 재사용성, 유지 관리성 및 확장성을 향상시키는 검증된 솔루션을 제공합니다. 2. PHP 디자인 패턴의 유형 PHP에는 다양한 디자인 패턴이 있으며 각 패턴에는 특정 목적이 있습니다. 가장 일반적인 패턴은 다음과 같습니다. 싱글톤 패턴: 클래스의 인스턴스가 하나만 있는지 확인합니다. 팩토리 패턴: 전달된 데이터를 기반으로 다양한 유형의 객체를 생성합니다. 전략 모드: 프로그램이 런타임 시 동작을 변경할 수 있도록 합니다. 관찰자 패턴: 객체가 이벤트를 구독하고 이벤트가 발생할 때 알림을 받을 수 있습니다. 3. 싱글톤 모드 예시 classSingleInstance{private

PHP의 싱글톤 패턴에 대한 일반적인 애플리케이션 시나리오 분석 개요: 싱글톤 패턴(SingletonPattern)은 클래스에 인스턴스가 하나만 있음을 보장하고 인스턴스에 액세스할 수 있는 전역 액세스 지점을 제공하는 생성 디자인 패턴입니다. PHP에서 싱글톤 모드를 사용하면 클래스의 인스턴스화 수와 리소스 사용량을 효과적으로 제한하고 코드의 성능과 유지 관리성을 향상시킬 수 있습니다. 이 기사에서는 일반적인 애플리케이션 시나리오를 분석하고 특정 PHP 코드 예제를 제공하여 싱글톤 패턴의 사용과 이점을 설명합니다. 데이터베이스 연결 파이프
