이전 기사에서는 Java8을 사용하여 관찰자 패턴 (1 부)을 구현하는 방법을 소개했습니다. 이 기사는 Java8 관찰자 패턴에 대한 관련 지식을 계속 소개합니다. 특정 내용은 다음과 같습니다.
스레드 안전 구현
이전 장에서는 현대의 Java 환경에서 관찰자 패턴의 구현을 소개합니다. 간단하지만 완전하지만이 구현은 스레드 안전 인 주요 문제를 무시합니다. 대부분의 열린 Java 응용 프로그램은 다중 스레드이며 관찰자 모드는 주로 다중 스레드 또는 비동기 시스템에서 사용됩니다. 예를 들어, 외부 서비스가 데이터베이스를 업데이트하는 경우 응용 프로그램은 메시지를 비동기로 수신 한 다음 외부 서비스를 직접 등록하고 듣는 대신 내부 구성 요소에 관찰자 모드에서 업데이트하도록 알립니다.
옵저버 모드의 스레드 안전은 주로 모드의 본문에 중점을 둡니다. 등록 된 리스너 컬렉션을 수정할 때 스레드 충돌이 발생할 수 있기 때문입니다. 예를 들어, 한 스레드는 새로운 리스너를 추가하려고 시도하는 반면, 다른 스레드는 새로운 동물 객체를 추가하려고 시도하여 모든 등록 된 리스너에게 알림을 유발합니다. 시퀀스 순서가 주어지면, 첫 번째 스레드는 등록 된 청취자가 추가 된 동물에 대한 알림을 받기 전에 새로운 청취자의 등록을 완료했을 수도 있고 아닐 수도 있습니다. 이것은 스레드 리소스 경쟁의 전형적인 사례이며,이 현상은 개발자에게 스레드 안전을 보장하기위한 메커니즘이 필요하다는 것을 알려줍니다.
이 문제에 대한 가장 쉬운 해결책은 다음과 같습니다. 등록 리스너 목록에 액세스하거나 수정하는 모든 작업은 다음과 같은 Java 동기화 메커니즘을 따라야합니다.
public synchronized AnimalAddedListener RegisteranimalAddedListener (AnimalAddedListener Listener) {/*.../} 공개 void UnregisteranimalAddedListener (AnimalAddedListener Listener) {/*.../} public synchronized void notifyanimaladdedlisteners (동물) {/*.}.이런 식으로 동시에, 하나의 스레드만이 등록 된 리스너 목록을 수정하거나 액세스 할 수 있는데, 이는 자원 경쟁 문제를 성공적으로 피할 수 있지만 새로운 문제가 발생하고 이러한 제약이 너무 엄격합니다 (동기화 된 키워드 및 Java 동의 모델에 대한 자세한 내용은 공식 웹 페이지를 참조하십시오). 메소드 동기화를 통해 리스너 목록에 대한 동시 액세스가 항상 관찰 될 수 있습니다. 리스너를 등록하고 취소하는 것은 리스너 목록의 쓰기 조작이며, 리스너가 액세스하도록 알리는 것은 읽기 전용 작업입니다. 알림을 통한 액세스는 읽기 작업이므로 다중 알림 작업을 동시에 수행 할 수 있습니다.
따라서, 리스너 등록 또는 취소가없는 한, 등록 된 리스너 목록에 대한 리소스 경쟁을 트리거하지 않고 동시 알림을 동시에 실행할 수있는 한 등록이 등록되지 않는 한, 등록이 등록되지 않는 한. 물론, 다른 상황에서의 자원 경쟁은 오랫동안 존재 해 왔습니다. 이 문제를 해결하기 위해 ReadWritelock의 리소스 잠금은 읽기 및 쓰기 작업을 별도로 관리하도록 설계되었습니다. Zoo Class의 스레드-안전 스레드 STREADSAFEZOO 구현 코드는 다음과 같습니다.
Public Class ThreadSafezoo {Private Final ReadWritelock readWritelock = New ReentRantreadWritelock (); 보호 된 최종 잠금 readlock = readwritelock.readlock (); 보호 된 최종 잠금 WriteLock = readwritelock.writelock (); 개인 목록 <ement> 동물 = New Arraylist <> (); 개인 목록 <QualeAddedListener> 청취자 = New ArrayList <> (); public void addAnimal (동물) {/ // 동물 목록에 동물을 추가하십시오. Learsersthis.notifyanimaladdedListeners (Animal);} public AnimalAddedListener RegisteranimalAddedListener (AnimalAddedListener Listener) {// this.writelock.lock ()을 작성하려면 청취자 목록을 잠그십시오. LockThis.writelock.unlock ();} 반환 청취자;} public void unregisteranimalAddedListener (eAgentAddedListener Listener) {// this.writelock.lock ()을 작성하려면 리스너 목록을 잠그십시오. lockthis.writelock.unlock ();}} public void notifyanimaladdedListeners (Animal Animal) {// reading this.readlock.lock ()에 대한 리스너 목록을 잠그십시오. 리더 잠금 해제 lockthis.readlock.unlock ();}}}이러한 배치를 통해 주제의 구현은 스레드 안전을 보장 할 수 있으며 여러 스레드가 동시에 알림을 발행 할 수 있습니다. 그러나 그럼에도 불구하고 여전히 무시할 수없는 두 가지 자원 경쟁 문제가 있습니다.
각 청취자에 대한 동시 액세스. 여러 스레드가 리스너에게 새로운 동물이 필요하다는 것을 알릴 수 있습니다. 즉, 청취자는 여러 스레드에 의해 동시에 호출 될 수 있습니다.
동물 목록에 동시에 접근 할 수 있습니다. 여러 실이 동물 목록에 동시에 객체를 추가 할 수 있습니다. 알림 순서에 영향을 미치는 경우 자원 경쟁으로 이어질 수 있으며,이 문제는이 문제를 피하기 위해 동시 작동 처리 메커니즘이 필요합니다. 등록 된 청취자 목록이 동물을 추가하라는 알림을받은 다음 Animal1을 추가 할 알림을 받으면 자원 경쟁이 이루어집니다. 그러나, Animal1 및 Animal2의 첨가가 상이한 실에 의해 수행되는 경우, Animal2 전에 Animal1의 첨가를 완료 할 수도있다. 구체적으로, 스레드 1은 리스너에게 알리고 모듈을 잠그기 전에 Animal1을 추가하고, 스레드 2는 Animal2를 추가하고 청취자에게 알리고, Thread 1은 청취자에게 Animal1에 추가되었음을 알립니다. 시퀀스 순서가 고려되지 않으면 자원 경쟁을 무시할 수 있지만 문제는 실제입니다.
청취자에게 동시에 접근합니다
동시 액세스 리스너는 청취자의 스레드 안전을 보장하여 구현할 수 있습니다. 클래스의 "자기 책임"의 정신을 고수하면서 청취자는 자체 스레드 안전을 보장하기위한 "의무"가 있습니다. 예를 들어, 위에서 계산 된 청취자의 경우 여러 실로 동물 수를 늘리거나 감소 시키면 스레드 안전 문제가 발생할 수 있습니다. 이 문제를 피하려면 동물 수의 계산은 원자 연산 (원자 변수 또는 메소드 동기화)이어야합니다. 특정 솔루션 코드는 다음과 같습니다.
공개 클래스 스레드 스레드 스레드 (Public Class SuredSafeCountinganimalAddedListener) emanemalAddedListener {개인 정적 원자체 동물성 동물 사도 (0);@ativeRidePublic void updateanimalAdded (동물 동물) {// 동물의 수를 증가시킨다.메소드 동기화 솔루션 코드는 다음과 같습니다.
Public Class CountinganimaladdedListener는 AnimalAddedListener를 구현합니다.
청취자는 자체 스레드 안전을 보장해야한다는 점을 강조해야합니다. 대상은 청취자에 액세스하고 수정하기위한 스레드 안전을 보장하는 대신 청취자의 내부 논리를 이해해야합니다. 그렇지 않으면 여러 과목이 동일한 리스너를 공유하는 경우 각 주제 클래스는 스레드 안전 코드를 다시 작성해야합니다. 분명히, 그러한 코드는 충분히 간결하지 않으므로 스레드-안전을 청취자 클래스에서 구현해야합니다.
청취자의 주문 알림
리스너가 순서대로 실행 해야하는 경우, 읽기 및 쓰기 잠금 장치는 요구를 충족시킬 수 없으며, Notify 함수의 호출 순서가 동물 동물원에 추가되는 순서와 일치하는지 확인하기 위해 새로운 메커니즘을 도입해야합니다. 일부 사람들은 메소드 동기화를 사용하여이를 구현하려고 시도했지만 Oracle 문서에서 메소드 동기화의 도입에 따라 메소드 동기화가 작동 실행의 주문 관리를 제공하지 않는다는 것을 알 수 있습니다. 원자 운영이 중단되지 않도록하고 FIFO (First-Come-First Execution)의 스레드 순서를 보장하지 않습니다. ReentrantreadWritelock은 이러한 실행 순서를 구현할 수 있으며 코드는 다음과 같습니다.
공개 클래스 OrderedThreadSafezoo {Private Final ReadWritElock readWritelock = 새로운 ReentrantreadWritelock (True); 보호 된 최종 잠금 readlock = readwritelock.readlock (); 보호 된 최종 잠금 WriteLock = readwritelock.writelock (); 개인 목록 <ement> 동물 = New Arraylist <> (); 개인 목록 <QualeAddedListener> 청취자 = New ArrayList <> (); public void addAnimal (동물) {/ // 동물 목록에 동물을 추가하십시오. Learsersthis.notifyanimaladdedListeners (Animal);} public AnimalAddedListener RegisteranimalAddedListener (AnimalAddedListener Listener) {// this.writelock.lock ()을 작성하려면 청취자 목록을 잠그십시오. LockThis.writelock.unlock ();} 반환 청취자;} public void unregisteranimalAddedListener (eAgentAddedListener Listener) {// this.writelock.lock ()을 작성하려면 리스너 목록을 잠그십시오. lockthis.writelock.unlock ();}} public void notifyanimaladdedListeners (Animal Animal) {// reading this.readlock.lock ()에 대한 리스너 목록을 잠그십시오. 리더 잠금 해제 lockthis.readlock.unlock ();}}}이러한 방식으로 등록, 등록 및 통지 기능은 FIFO (First-In-First-Out) 순서대로 읽기 및 쓰기 잠금 권한을 얻습니다. 예를 들어, 스레드 1은 리스너를 등록하고, 스레드 2는 등록 된 리스너에게 등록 된 리스너에게 알리려고 시도하고, 스레드 2는 읽기 전용 잠금 장치를 기다리고 있고, 공정 주문 방법을 채택하고, 스레드 1은 등록 작업을 먼저 완료하고, 스레드 2는 리스너에게 알리지 않을 수 있습니다. 이를 통해 실행 순서와 작업의 시작 순서가 일관되게 유지됩니다.
스레드 2가 리소스를 점유하기 위해 먼저 큐를 큐를 타지 만 스레드 3은 여전히 스레드 2 이전에 리소스 잠금을 얻을 수 있지만 스레드 2는 스레드 3보다 먼저 리스너에게 알릴 수 없다는 것을 보장 할 수 없습니다. 문제의 키는 다음과 같습니다. 공정 주문 방법은 자원이 적용되는 순서대로 스레드가 실행되도록 보장 할 수 없습니다. 읽기 및 쓰기 잠금의 순서 메커니즘은 매우 복잡합니다. 잠금의 논리가 문제를 해결하기에 충분한 지 확인하려면 ReentrantreadWritelock의 공식 문서를 참조해야합니다.
스레드 안전성이 지금까지 구현되었으며, 주제의 논리를 추출하고 Mixin 클래스를 반복 가능한 코드 단위로 캡슐화하는 장점과 단점은 다음 장에서 도입 될 것입니다.
믹스 인 클래스에 캡슐화 된 테마 논리
위에서 언급 한 관찰자 패턴 설계 구현을 Target Mixin 클래스로 캡슐화하는 것은 매우 매력적입니다. 일반적으로 관찰자 모드의 관찰자는 등록 된 청취자 모음을 포함합니다. 새로운 청취자 등록을 담당하는 기능 등록 기능; 등록되지 않은 등록되지 않은 함수를 취소하고 리스너에 알리는 기능을 알려주는 등록 기능. 동물원의 위의 예에서는 문제에 동물 목록이 필요하다는 점을 제외하고 동물원 수업의 다른 모든 작전은 주제의 논리를 구현하는 것입니다.
Mixin 클래스의 경우는 다음과 같습니다. 코드를보다 간결하게 만들려면 스레드 안전에 대한 코드가 여기에서 제거됩니다.
공개 초록 클래스 관찰 정보 서브 jectmixin <LeaterType> {개인 목록 <LeaterType> 청취자 = new ArrayList <> (); public threateRtype registerListener (LeargerType Listener) {// 리시너 목록에 리스너를 추가하십시오. 리스너) {// 등록 된 리스너 this.listeners.remove (리스너);} 공개 void notifylisteners (소비자 <? super learsertype> algorithm) {// 각 청취자 this.listeners.foreach (algorithm)에서 일부 함수를 실행합니다.등록 된 리스너 유형의 인터페이스 정보가 제공되지 않기 때문에 특정 리스너에게 직접 알릴 수 없으므로 알림 기능의 보편성을 보장하고 클라이언트가 각 리스너에게 적용 할 수있는 일반 매개 변수 유형의 매개 변수 일치하는 매개 변수 일치와 같은 일부 기능을 추가 할 수 있어야합니다. 특정 구현 코드는 다음과 같습니다.
공개 클래스 zoousingmixin은 관찰 정보를 확장합니다. Learger.updateanimaladded (동물));}}
Mixin Class 기술의 가장 큰 장점은 각 주제 클래스의 논리를 반복하지 않고 관찰자 패턴 대상을 반복 가능한 클래스로 캡슐화하는 것입니다. 또한이 방법은 동물원 클래스의 구현을 더 간단하게 만들어 청취자를 저장하고 알리는 방법을 고려하지 않고 동물 정보를 저장합니다.
그러나 Mixin 클래스를 사용하는 것이 단순히 이점이 아닙니다. 예를 들어 여러 유형의 청취자를 저장하려면 어떻게해야합니까? 예를 들어, 리스너 유형 AnimalLemovedListener를 저장해야합니다. Mixin 클래스는 추상 클래스입니다. Java에서 여러 초록 클래스를 동시에 상속받을 수 없으며 Mixin 클래스는 대신 인터페이스를 사용하여 구현할 수 없습니다. 인터페이스에 상태가 포함되어 있지 않으며, 옵저버 모드의 상태를 사용하여 등록 된 리스너 목록을 저장해야하기 때문입니다.
한 가지 해결책은 동물이 증가하고 감소 할 때 알림을받을 청취자 유형 Zoolistener를 만드는 것입니다. 코드는 다음과 같습니다.
공공 인터페이스 Zoolistener {public void onanimaladded (동물 동물); public void onanimalremoved (동물);}이러한 방식 으로이 인터페이스를 사용하여 청취자 유형을 사용하여 동물원 주에서 다양한 변경 사항을 모니터링 할 수 있습니다.
공공 클래스 zoosingmixin은 관찰 정보를 확장합니다. Learger.onanimaladded (동물));} public void removeanimal (동물 동물) {// 동물 목록에서 동물을 제거하십시오.여러 리스너 유형을 하나의 리스너 인터페이스로 결합하면 위에서 언급 한 문제가 해결되지만 여전히 단점이 있으며 다음 장에서는 자세히 설명합니다.
다중 방법 청취자 및 어댑터
위의 방법에서, 리스너 인터페이스가 너무 많은 함수를 구현하면 인터페이스가 너무 장점이됩니다. 예를 들어, Swing Mouselistener에는 5 가지 필요한 기능이 포함되어 있습니다. 마우스 클릭 이벤트를 사용하는 한이 5 가지 기능을 추가해야합니다. 빈 기능 본체를 사용하여 나머지 기능을 구현할 가능성이 높으며, 이는 의심 할 여지없이 코드에 불필요한 혼란을 초래할 것입니다.
한 가지 해결책은 어댑터를 만드는 것입니다 (개념은 GOF가 제안한 어댑터 패턴에서 나옵니다). 리스너 인터페이스의 작동은 특정 리스너 클래스의 상속을위한 추상 함수 형태로 구현됩니다. 이러한 방식으로 특정 청취자 클래스는 필요한 기능을 선택하고 어댑터가 필요하지 않은 함수에 대한 기본 작업을 사용할 수 있습니다. 예를 들어, 위의 예제의 Zoolistener 클래스에서 ZOOADAPTER 작성 (어댑터의 이름 지정 규칙은 리스너와 일치하므로 클래스 이름의 리스너를 어댑터로 변경하면됩니다). 코드는 다음과 같습니다.
공공 클래스 ZooAdapter는 Zoolistener {@OverridePublic void onanimaladded (동물 동물) {} @OverridePublic void onanimalRemoved (동물) {}}을 구현합니다.언뜻보기 에이 어댑터 클래스는 중요하지 않지만 편의를 과소 평가할 수는 없습니다. 예를 들어 다음 특정 클래스의 경우 유용한 기능을 선택하십시오.
공개 클래스 nameprinterzooadapter 확장 Zooadapter {@overridepublic void onanimaladded (동물) {// addsystem.out.println 인 동물의 이름을 인쇄합니다.어댑터 클래스의 함수를 구현할 수있는 두 가지 대안이 있습니다. 하나는 기본 함수를 사용하는 것입니다. 다른 하나는 리스너 인터페이스와 어댑터 클래스를 특정 클래스로 병합하는 것입니다. 기본 기능은 Java 8에서 새로 제안되므로 개발자는 인터페이스에서 기본 (Defense) 구현 방법을 제공 할 수 있습니다.
Java 라이브러리에 대한이 업데이트는 주로 개발자가 이전 버전의 코드를 변경하지 않고 프로그램 확장을 구현할 수있게 하므로이 방법을주의해서 사용해야합니다. 여러 번 사용한 후 일부 개발자는 이러한 방식으로 작성된 코드가 충분히 전문적이지 않다고 생각하며 일부 개발자는 이것이 Java 8의 기능이라고 생각합니다. 무엇이든 관계 없이이 기술의 원래 의도가 무엇인지 이해하고 특정 질문에 따라 사용할지 여부를 결정해야합니다. 기본 함수를 사용하여 구현 된 Zoolistener 인터페이스 코드는 다음과 같습니다.
공개 인터페이스 Zoolistener {기본 공공 void onanimaladded (동물 동물) {} 기본 공공 공개 onanimalRemoved (동물 동물) {}}기본 함수를 사용하면 인터페이스의 특정 클래스를 구현하면 인터페이스에서 모든 함수를 구현할 필요는 없지만 필요한 기능을 선택적으로 구현하십시오. 이는 인터페이스 확장 문제에 대한 비교적 간단한 솔루션이지만 개발자는이를 사용할 때 더 많은주의를 기울여야합니다.
두 번째 솔루션은 관찰자 모드를 단순화하고, 리스너 인터페이스를 생략하고, 특정 클래스를 사용하여 리스너의 기능을 구현하는 것입니다. 예를 들어, Zoolistener 인터페이스는 다음과 같습니다.
공공 클래스 Zoolistener {public void onanimaladded (동물 동물) {} public void onanimalremoved (동물 동물) {}}이 솔루션은 관찰자 패턴의 계층 구조를 단순화하지만 모든 경우에 적용 할 수는 없습니다. 리스너 인터페이스가 특정 클래스로 병합되면 특정 리스너는 여러 청취 인터페이스를 구현할 수 없기 때문입니다. 예를 들어, AnimalAddedListener 및 AnimalLeMovedListener 인터페이스가 동일한 콘크리트 클래스로 작성된 경우 단일 특정 리스너는 동시에 두 인터페이스를 동시에 구현할 수 없습니다. 또한, 리스너 인터페이스의 의도는 특정 클래스의 의도보다 더 분명합니다. 전자는 다른 클래스에 인터페이스를 제공하는 것이 분명하지만 후자는 그다지 명백하지는 않습니다.
적절한 문서가 없으면 개발자는 인터페이스의 역할을 수행하고 해당 기능을 모두 구현하는 클래스가 이미 있다는 것을 알지 못할 것입니다. 또한 클래스가 특정 인터페이스에 맞지 않기 때문에 클래스 이름에는 어댑터가 포함되어 있지 않으므로 클래스 이름은이 의도를 구체적으로 암시하지 않습니다. 요약하면, 특정 문제는 특정 방법을 선택해야하며 방법은 전능하지 않습니다.
다음 장을 시작하기 전에 어댑터는 관찰 모드, 특히 이전 버전의 Java 코드에서 일반적이라는 점을 언급하는 것이 중요합니다. 스윙 API는 Adapter를 기반으로 구현되며, 많은 오래된 응용 프로그램이 Java 5 및 Java 6의 관찰자 패턴에 사용되므로 동물원 케이스의 리스너는 어댑터가 필요하지 않을 수 있지만 어댑터의 목적을 이해해야합니다. 기존 코드에서 사용할 수 있기 때문에 어댑터의 목적을 이해해야합니다. 다음 장에서는 시간 집약적 인 청취자를 소개합니다. 이 유형의 청취자는 시간이 많이 걸리는 작업을 수행하거나 비동기 호출을 할 수 있으며 즉시 반환 값을 줄 수 없습니다.
복잡하고 차단 청취자
관찰자 패턴에 대한 한 가지 가정은 함수가 실행되면 일련의 리스너가 호출되지만이 프로세스가 발신자에게 완전히 투명하다고 가정합니다. 예를 들어, 클라이언트 코드가 동물원에 동물을 추가하면 반품이 성공하기 전에 일련의 청취자가 호출되는 것으로 알려져 있지 않습니다. 청취자의 실행이 오랜 시간이 걸리면 (시간이 리스너 수, 각 청취자의 실행 시간에 영향을받는 경우), 클라이언트 코드는이 간단한 동물 운영 증가의 시간 부작용을 알고 있습니다.
이 기사는이 주제를 포괄적 인 방식으로 논의 할 수 없습니다. 다음은 개발자가 복잡한 청취자에게 전화 할 때주의를 기울여야하는 것입니다.
리스너는 새 스레드를 시작합니다. 새 스레드가 시작된 후 새 스레드에서 리스너 로직을 실행하면서 리스너 기능의 처리 결과가 반환되고 다른 리스너가 실행됩니다.
주제는 새로운 스레드를 시작합니다. 등록 된 리스너 목록의 기존 선형 반복과 달리 피사체의 알림 기능은 새 스레드를 다시 시작한 다음 새 스레드의 리스너 목록을 반복합니다. 이를 통해 알림 기능은 다른 리스너 작업을 수행하면서 반환 값을 출력 할 수 있습니다. 리스너 목록이 동시 수정을받지 않도록 스레드 안전 메커니즘이 필요하다는 점에 유의해야합니다.
큐 리스너는 일련의 스레드로 청취 기능을 호출하고 수행합니다. 청취자 작업을 일부 기능으로 캡슐화하고 청취자 목록에 간단한 반복 호출 대신 대기합니다. 이 리스너가 큐에 저장되면 스레드는 큐에서 단일 요소를 팝하고 청취 로직을 실행할 수 있습니다. 이것은 생산자 소비자 문제와 유사합니다. 알림 프로세스는 실행 가능 함수의 대기열을 생성 한 다음 스레드는 차례로 대기열을 차례로 꺼내 이러한 기능을 실행합니다. 이 기능은 청취자 기능이 호출되는 시간이 아닌 생성 된 시간을 저장해야합니다. 예를 들어, 리스너를 호출 할 때 생성 된 함수는 기능이 포인트를 저장해야합니다. 이 기능은 Java의 다음 작업과 유사합니다.
Public Class AnimalAddedFunctor {Private Final AnimalAddedListener Listener; 개인 최종 동물 매개 변수; Public AnimalAddedFunctor (AnimalAddedListener 청취자, 동물 매개 변수) {this.listener = 청취자; Parameter = 매개 변수;} public void execute () {// creationthis.listener.updateanimaladded (this.parameter);}}함수는 큐에서 생성되고 저장되며 언제든지 호출 할 수 있으므로 목록 목록 목록을 가로 질러 해당 작업을 수행 할 필요가 없습니다. 리스너를 활성화하는 각 함수가 큐로 밀려 나면 "소비자 스레드"는 운영 권한을 클라이언트 코드에 반환합니다. "소비자 스레드"는 마치 리스너가 Notify 함수에 의해 활성화되는 것처럼 나중에 이러한 기능을 실행합니다. 이 기술을 다른 언어에서 매개 변수 바인딩이라고하며 위의 예제에 맞습니다. 기술의 본질은 리스너의 매개 변수를 저장 한 다음 execute () 함수를 직접 호출하는 것입니다. 리스너가 여러 매개 변수를 수신하면 처리 방법이 유사합니다.
리스너의 실행 순서를 저장하려면 포괄적 인 정렬 메커니즘을 도입해야합니다. 반응식 1에서 리스너는 정상 순서로 새 스레드를 활성화하여 리스너가 등록 순서로 실행되도록합니다. 반응식 2에서 대기열은 정렬을 지원하며 그 기능은 대기열을 입력 순서대로 실행됩니다. 간단히 말해서, 개발자는 청취자의 다중 스레드 실행의 복잡성에주의를 기울이고 신중하게 처리하여 필요한 기능을 구현해야합니다.
결론
관찰자 모델이 1994 년 에이 책에 작성되기 전에 이미 주류 소프트웨어 설계 모델로 소프트웨어 설계에서 발생하는 문제에 대한 많은 만족스러운 솔루션을 제공합니다. Java는 항상이 패턴을 사용하는 리더였으며 표준 라이브러리 에서이 패턴을 캡슐화했지만 Java가 버전 8으로 업데이트 되었다면 고전적인 패턴 사용을 다시 검사해야합니다. Lambda 표현 및 기타 새로운 구조의 출현 으로이 "오래된"패턴은 새로운 활력을 가져 왔습니다. 오래된 프로그램을 처리하든이 장기적인 방법을 사용하여 새로운 문제를 해결하기 위해 특히 숙련 된 Java 개발자의 경우 관찰자 패턴이 개발자의 주요 도구입니다.
OneApm은 엔드 투 엔드 Java 응용 프로그램 성능 솔루션을 제공합니다. 우리는 모든 일반적인 Java 프레임 워크 및 애플리케이션 서버를 지원하여 시스템 병목 현상을 신속하게 발견하고 이상의 근본 원인을 찾을 수 있도록 도와줍니다. 1 분 수준과 경험을 즉시 배포하면 Java 모니터링이 쉬운 적이 없습니다. 더 많은 기술 기사를 읽으려면 OneApm의 공식 기술 블로그를 방문하십시오.
위의 내용은 Java8을 사용하여 관찰자 모드 (2 부)를 구현하는 방법을 소개합니다. 모든 사람에게 도움이되기를 바랍니다!