상세 컨텐츠

본문 제목

Reactive Programming with JDK 9 Flow API 번역

IT/프로그래밍

by James Lee. 2017. 10. 20. 17:55

본문

Edit

Reactive Programming with JDK 9 Flow API 번역

이 문서는 오라클 커뮤니티 문서를 개인 공부 목적으로 일부 번역한 내용을 공유하는 것입니다. 오역이나 번역이 매끄럽지 않을 수 있습니다. 잘못된 부분이 있다면 피드백 바랍니다.
(하단의 Processor 파트는 아직 학습하지 않은 관계로 번역을 하지 않았습니다.)
Publisher를 게시자로 번역하였고, Subscriber를 구독자로 번역하였습니다. 중간에 용어가 종종 혼용됩니다.

리액티브 프로그래밍이란?

리액티브 프로그래밍은 데이터 항목의 비동기 스트림을 처리하는 것입니다. 여기서 애플리케이션은 발생하는 데이터 항목에 반응합니다. 데이터 스트림은 본질적으로 시간이 지남에 따라 발생하는 일련의 데이터 항목입니다. 이 모델은 메모리 내 데이터를 반복하는 것과 비교하여 데이터가 스트림으로 처리되기 때문에 메모리를 더 효율적으로 처리합니다.

리액티브 프로그래밍 모델에는 게시자(Publisher)와 구독자(Subscriber)가 있습니다. 게시자는 구독자가 비동기적으로 구독하는 데이터 스트림을 게시합니다.

이 모델은 또한 프로세서를 통해 스트림에서 작동하는 고차 함수를 도입하는 메커니즘을 제공합니다. 프로세서는 게시자 또는 구독자를 변경할 필요없이 데이터 스트림을 변환합니다. 프로세서 (또는 프로세서 체인)는 게시자와 구독자 사이에 위치하여 데이터의 한 스트림을 다른 스트림으로 변환합니다. 게시자와 구독자는 데이터 스트림에 발생하는 변환과 독립적입니다.

리액티브 프로그래밍의 장점

  • Simpler code, making it more readable. (코드가 간단해서 가독성 상승)
  • Abstracts away from boiler plate code to focus on business logic.
  • Abstracts away from low-level threading, synchronization, and concurrency issues. (저수준 스레딩, 동기화 및 동시성 문제를 추상화)
  • Stream processing implies memory efficient (스트림 처리는 메모리를 효율적으로 처리)
  • The model can be applied almost everywhere to solve almost any kind of problem. (이 모델은 거의 모든 종류의 문제를 해결하기 위하여 거의 모든 곳에 적용 할 수 있습니다. (.....? 너무 믿지는 않는 것이 좋습니다.)

JDK9의 Flow API

JDK 9의 Flow API는 실질적인 표준인 Reactive Streams Specification에 해당합니다. Reactive Streams Specification은 Reactive Programming을 표준화하기 위한 이니셔티브 중 하나입니다. 여러 구현체가 이미 Reactive Streams Specification을 지원합니다.

Flow API (및 Reactive Streams API)는 어떤 면에서 Iterator 및 Observer 패턴의 아이디어를 조합 한 것입니다. Iterator는 응용 프로그램이 소스에서 항목을 가져오는 풀 모델입니다. 옵저버는 푸시 모델로, 소스의 항목이 응용 프로그램으로 푸시됩니다. Flow API를 사용하여 응용 프로그램은 처음에 N 개의 항목을 요청한 다음 게시자는 N 개까지의 항목을 구독자에게 푸시합니다. 그래서 Pull과 Push 프로그래밍 모델이 혼합되어 있습니다.

Flow API Interfaces

@FunctionalInterface
public static interface Flow.Publisher<T> {
public void subscribe(Flow.Subscriber<? super T> subscriber);
}
public static interface Flow.Subscriber<T> {
public void onSubscribe(Flow.Subscription subscription);
public void onNext(T item) ;
public void onError(Throwable throwable) ;
public void onComplete() ;
}
public static interface Flow.Subscription {
public void request(long n);
public void cancel() ;
}
public static interface Flow.Processor<T,R> extends Flow.Subscriber<T>, Flow.Publisher<R> {
}

Subscriber callback

구독자(Subscriber)는 콜백을 위해 게시자(Publisher)를 구독합니다.
데이터는 요청하지 않는 한 구독자에게 푸시되지 않습니다. 보통은 여러 항목들을 함께 요청합니다. 주어진 구독에 대한 구독자 메서드 호출은 엄격하게 명령받습니다. (Subscriber method invocations for a given Subscription are strictly ordered.)

애플리케이션은 구독자가 사용할 수 있는 아래의 콜백에 반응합니다.

  1. onSubscribe : 지정된 Subscription(구독)에 대해 다른 Subscriber(구독자)메서드를 호출하기 전에 호출되는 메서드입니다.
  2. onNext : Subscription의 다음 항목으로 호출되는 메서드입니다.
  3. onError : Publisher(게시자) 또는 Subscription에서 발생하는 복구 할 수 없는 오류로 인해 호출된 메서드입니다. 그 후에는 Subscription으로 다른 Subscriber 메서드가 호출되지 않습니다. Publisher가 Subscriber에게 항목을 발행하지 못하게 하는 오류가 발생하면 해당 Subscriber는 onError를 수신한 다음 더 메시지를 받지 않습니다.
  4. onComplete : 아직 오류로 종료되지 않은 Subscription에 대해 추가 Subscriber 메서드 호출이 발생하지 않는 것으로 알려진 후 Subscription에서 다른 Subscriber 메서드를 호출하지 않는 경우 호출되는 메서드입니다. 더 이상의 메시지가 발행되지 않을 것으로 알려진 경우, Subscriber는 onComplete를 실행합니다.

Sample Subscriber

import java.util.concurrent.Flow.*;
...
public class MySubscriber<T> implements Subscriber<T> {
private Subscription subscription;
@Override
public void onSubscribe(Subscription subscription) {
this.subscription = subscription;
subscription.request(1); //a value of Long.MAX_VALUE may be considered as effectively unbounded
}
@Override
public void onNext(T item) {
System.out.println("Got : " + item);
subscription.request(1); //a value of Long.MAX_VALUE may be considered as effectively unbounded
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("Done");
}
}

게시자 (Publisher)

게시자는 등록 된 구독자에게 데이터 항목의 스트림을 게시합니다. 일반적으로 Executor를 사용하여 항목을 비동기 적으로 구독자에게 게시합니다.
게시자는 각 구독에 대한 Subscriber 메서드 호출을 strictly하게 요청합니다.(Publishers ensure that Subscriber method invocations for each subscription are strictly ordered.)

아래는 JDK의 SubmissionPublisher를 사용하여 구독자에게 데이터 항목의 스트림을 게시하는 예시입니다.

import java.util.concurrent.SubmissionPublisher;
...
//Create Publisher
SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
//Register Subscriber
MySubscriber<String> subscriber = new MySubscriber<>();
publisher.subscribe(subscriber);
//Publish items
System.out.println("Publishing Items...");
String[] items = {"1", "x", "2", "x", "3", "x"};
Arrays.asList(items).stream().forEach(i -> publisher.submit(i));
publisher.close();

구독 (The Subscription)

Flow.Publisher와 Flow.Subscriber를 연결합니다. 구독자는 요청이있을 때만 항목을 수신하며 구독을 통해 언제든지 취소 할 수 있습니다.

Subscription Method

  1. request : 지정된 수의 n 개 항목을 구독에 대한 현재 충족되지 않은 수요에 추가합니다.
  2. cancel : 구독자가 메시지 수신을 중지합니다.
%23%20Reactive%20Programming%20with%20JDK%209%20Flow%20API%20%uBC88%uC5ED%0A%0A@%28Java%29%5B%uD2F0%uC2A4%uD1A0%uB9AC%5D%0A%0A%uC774%20%uBB38%uC11C%uB294%20%5B%uC624%uB77C%uD074%20%uCEE4%uBBA4%uB2C8%uD2F0%20%uBB38%uC11C%5D%28https%3A//community.oracle.com/docs/DOC-1006738%29%uB97C%20%uAC1C%uC778%20%uACF5%uBD80%20%uBAA9%uC801%uC73C%uB85C%20%uC77C%uBD80%20%uBC88%uC5ED%uD55C%20%uB0B4%uC6A9%uC744%20%uACF5%uC720%uD558%uB294%20%uAC83%uC785%uB2C8%uB2E4.%20%uC624%uC5ED%uC774%uB098%20%uBC88%uC5ED%uC774%20%uB9E4%uB044%uB7FD%uC9C0%20%uC54A%uC744%20%uC218%20%uC788%uC2B5%uB2C8%uB2E4.%20%uC798%uBABB%uB41C%20%uBD80%uBD84%uC774%20%uC788%uB2E4%uBA74%20%uD53C%uB4DC%uBC31%20%uBC14%uB78D%uB2C8%uB2E4.%0A%28%uD558%uB2E8%uC758%20%60Processor%60%20%uD30C%uD2B8%uB294%20%uC544%uC9C1%20%uD559%uC2B5%uD558%uC9C0%20%uC54A%uC740%20%uAD00%uACC4%uB85C%20%uBC88%uC5ED%uC744%20%uD558%uC9C0%20%uC54A%uC558%uC2B5%uB2C8%uB2E4.%29%0APublisher%uB97C%20%uAC8C%uC2DC%uC790%uB85C%20%uBC88%uC5ED%uD558%uC600%uACE0%2C%20Subscriber%uB97C%20%uAD6C%uB3C5%uC790%uB85C%20%uBC88%uC5ED%uD558%uC600%uC2B5%uB2C8%uB2E4.%20%uC911%uAC04%uC5D0%20%uC6A9%uC5B4%uAC00%20%uC885%uC885%20%uD63C%uC6A9%uB429%uB2C8%uB2E4.%0A%0A%23%23%23%20%uB9AC%uC561%uD2F0%uBE0C%20%uD504%uB85C%uADF8%uB798%uBC0D%uC774%uB780%3F%0A%0A%uB9AC%uC561%uD2F0%uBE0C%20%uD504%uB85C%uADF8%uB798%uBC0D%uC740%20%uB370%uC774%uD130%20%uD56D%uBAA9%uC758%20%uBE44%uB3D9%uAE30%20%uC2A4%uD2B8%uB9BC%uC744%20%uCC98%uB9AC%uD558%uB294%20%uAC83%uC785%uB2C8%uB2E4.%20%uC5EC%uAE30%uC11C%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC740%20%uBC1C%uC0DD%uD558%uB294%20%uB370%uC774%uD130%20%uD56D%uBAA9%uC5D0%20%uBC18%uC751%uD569%uB2C8%uB2E4.%20%uB370%uC774%uD130%20%uC2A4%uD2B8%uB9BC%uC740%20%uBCF8%uC9C8%uC801%uC73C%uB85C%20%uC2DC%uAC04%uC774%20%uC9C0%uB0A8%uC5D0%20%uB530%uB77C%20%uBC1C%uC0DD%uD558%uB294%20%uC77C%uB828%uC758%20%uB370%uC774%uD130%20%uD56D%uBAA9%uC785%uB2C8%uB2E4.%20%uC774%20%uBAA8%uB378%uC740%20%uBA54%uBAA8%uB9AC%20%uB0B4%20%uB370%uC774%uD130%uB97C%20%uBC18%uBCF5%uD558%uB294%20%uAC83%uACFC%20%uBE44%uAD50%uD558%uC5EC%20%uB370%uC774%uD130%uAC00%20%uC2A4%uD2B8%uB9BC%uC73C%uB85C%20%uCC98%uB9AC%uB418%uAE30%20%uB54C%uBB38%uC5D0%20**%uBA54%uBAA8%uB9AC%uB97C%20%uB354%20%uD6A8%uC728%uC801%uC73C%uB85C%20%uCC98%uB9AC%uD569%uB2C8%uB2E4.**%0A%0A%uB9AC%uC561%uD2F0%uBE0C%20%uD504%uB85C%uADF8%uB798%uBC0D%20%uBAA8%uB378%uC5D0%uB294%20%uAC8C%uC2DC%uC790%28Publisher%29%uC640%20%uAD6C%uB3C5%uC790%28Subscriber%29%uAC00%20%uC788%uC2B5%uB2C8%uB2E4.%20%uAC8C%uC2DC%uC790%uB294%20%uAD6C%uB3C5%uC790%uAC00%20%uBE44%uB3D9%uAE30%uC801%uC73C%uB85C%20%uAD6C%uB3C5%uD558%uB294%20%uB370%uC774%uD130%20%uC2A4%uD2B8%uB9BC%uC744%20%uAC8C%uC2DC%uD569%uB2C8%uB2E4.%0A%0A%uC774%20%uBAA8%uB378%uC740%20%uB610%uD55C%20%uD504%uB85C%uC138%uC11C%uB97C%20%uD1B5%uD574%20%uC2A4%uD2B8%uB9BC%uC5D0%uC11C%20%uC791%uB3D9%uD558%uB294%20%uACE0%uCC28%20%uD568%uC218%uB97C%20%uB3C4%uC785%uD558%uB294%20%uBA54%uCEE4%uB2C8%uC998%uC744%20%uC81C%uACF5%uD569%uB2C8%uB2E4.%20%uD504%uB85C%uC138%uC11C%uB294%20%uAC8C%uC2DC%uC790%20%uB610%uB294%20%uAD6C%uB3C5%uC790%uB97C%20%uBCC0%uACBD%uD560%20%uD544%uC694%uC5C6%uC774%20%uB370%uC774%uD130%20%uC2A4%uD2B8%uB9BC%uC744%20%uBCC0%uD658%uD569%uB2C8%uB2E4.%20%uD504%uB85C%uC138%uC11C%20%28%uB610%uB294%20%uD504%uB85C%uC138%uC11C%20%uCCB4%uC778%29%uB294%20%uAC8C%uC2DC%uC790%uC640%20%uAD6C%uB3C5%uC790%20%uC0AC%uC774%uC5D0%20%uC704%uCE58%uD558%uC5EC%20%uB370%uC774%uD130%uC758%20%uD55C%20%uC2A4%uD2B8%uB9BC%uC744%20%uB2E4%uB978%20%uC2A4%uD2B8%uB9BC%uC73C%uB85C%20%uBCC0%uD658%uD569%uB2C8%uB2E4.%20%uAC8C%uC2DC%uC790%uC640%20%uAD6C%uB3C5%uC790%uB294%20%uB370%uC774%uD130%20%uC2A4%uD2B8%uB9BC%uC5D0%20%uBC1C%uC0DD%uD558%uB294%20%uBCC0%uD658%uACFC%20%uB3C5%uB9BD%uC801%uC785%uB2C8%uB2E4.%0A%0A%21%5BAlt%20text%5D%28./1508327734408.png%29%0A%0A%23%23%23%20%uB9AC%uC561%uD2F0%uBE0C%20%uD504%uB85C%uADF8%uB798%uBC0D%uC758%20%uC7A5%uC810%0A%0A-%20Simpler%20code%2C%20making%20it%20more%20readable.%20%28%uCF54%uB4DC%uAC00%20%uAC04%uB2E8%uD574%uC11C%20%uAC00%uB3C5%uC131%20%uC0C1%uC2B9%29%0A-%20Abstracts%20away%20from%20boiler%20plate%20code%20to%20focus%20on%20business%20logic.%0A-%20Abstracts%20away%20from%20low-level%20threading%2C%20synchronization%2C%20and%20concurrency%20issues.%20%28%uC800%uC218%uC900%20%uC2A4%uB808%uB529%2C%20%uB3D9%uAE30%uD654%20%uBC0F%20%uB3D9%uC2DC%uC131%20%uBB38%uC81C%uB97C%20%uCD94%uC0C1%uD654%29%0A-%20Stream%20processing%20implies%20memory%20efficient%20%28%uC2A4%uD2B8%uB9BC%20%uCC98%uB9AC%uB294%20%uBA54%uBAA8%uB9AC%uB97C%20%uD6A8%uC728%uC801%uC73C%uB85C%20%uCC98%uB9AC%29%0A-%20The%20model%20can%20be%20applied%20almost%20everywhere%20to%20solve%20almost%20any%20kind%20of%20problem.%20%28%uC774%20%uBAA8%uB378%uC740%20%uAC70%uC758%20%uBAA8%uB4E0%20%uC885%uB958%uC758%20%uBB38%uC81C%uB97C%20%uD574%uACB0%uD558%uAE30%20%uC704%uD558%uC5EC%20%uAC70%uC758%20%uBAA8%uB4E0%20%uACF3%uC5D0%20%uC801%uC6A9%20%uD560%20%uC218%20%uC788%uC2B5%uB2C8%uB2E4.%20%28%7E%7E.....%3F%20%uB108%uBB34%20%uBBFF%uC9C0%uB294%20%uC54A%uB294%20%uAC83%uC774%20%uC88B%uC2B5%uB2C8%uB2E4.%7E%7E%29%0A%0A%23%23%23%20JDK9%uC758%20Flow%20API%0A%0AJDK%209%uC758%20Flow%20API%uB294%20%uC2E4%uC9C8%uC801%uC778%20%uD45C%uC900%uC778%20Reactive%20Streams%20Specification%uC5D0%20%uD574%uB2F9%uD569%uB2C8%uB2E4.%20Reactive%20Streams%20Specification%uC740%20Reactive%20Programming%uC744%20%uD45C%uC900%uD654%uD558%uAE30%20%uC704%uD55C%20%uC774%uB2C8%uC154%uD2F0%uBE0C%20%uC911%20%uD558%uB098%uC785%uB2C8%uB2E4.%20%uC5EC%uB7EC%20%uAD6C%uD604%uCCB4%uAC00%20%uC774%uBBF8%20Reactive%20Streams%20Specification%uC744%20%uC9C0%uC6D0%uD569%uB2C8%uB2E4.%0A%0AFlow%20API%20%28%uBC0F%20Reactive%20Streams%20API%29%uB294%20%uC5B4%uB5A4%20%uBA74%uC5D0%uC11C%20Iterator%20%uBC0F%20Observer%20%uD328%uD134%uC758%20%uC544%uC774%uB514%uC5B4%uB97C%20%uC870%uD569%20%uD55C%20%uAC83%uC785%uB2C8%uB2E4.%20Iterator%uB294%20%uC751%uC6A9%20%uD504%uB85C%uADF8%uB7A8%uC774%20%uC18C%uC2A4%uC5D0%uC11C%20%uD56D%uBAA9%uC744%20%uAC00%uC838%uC624%uB294%20%uD480%20%uBAA8%uB378%uC785%uB2C8%uB2E4.%20%uC635%uC800%uBC84%uB294%20%uD478%uC2DC%20%uBAA8%uB378%uB85C%2C%20%uC18C%uC2A4%uC758%20%uD56D%uBAA9%uC774%20%uC751%uC6A9%20%uD504%uB85C%uADF8%uB7A8%uC73C%uB85C%20%uD478%uC2DC%uB429%uB2C8%uB2E4.%20Flow%20API%uB97C%20%uC0AC%uC6A9%uD558%uC5EC%20%uC751%uC6A9%20%uD504%uB85C%uADF8%uB7A8%uC740%20%uCC98%uC74C%uC5D0%20N%20%uAC1C%uC758%20%uD56D%uBAA9%uC744%20%uC694%uCCAD%uD55C%20%uB2E4%uC74C%20%uAC8C%uC2DC%uC790%uB294%20N%20%uAC1C%uAE4C%uC9C0%uC758%20%uD56D%uBAA9%uC744%20%uAD6C%uB3C5%uC790%uC5D0%uAC8C%20%uD478%uC2DC%uD569%uB2C8%uB2E4.%20%uADF8%uB798%uC11C%20Pull%uACFC%20Push%20%uD504%uB85C%uADF8%uB798%uBC0D%20%uBAA8%uB378%uC774%20%uD63C%uD569%uB418%uC5B4%20%uC788%uC2B5%uB2C8%uB2E4.%0A%0A%21%5BAlt%20text%5D%28./1508329956594.png%29%0A%0A%23%23%23%20Flow%20API%20Interfaces%0A%0A%60%60%60%0A@FunctionalInterface%20%20%20%0Apublic%20static%20interface%20Flow.Publisher%3CT%3E%20%7B%20%20%0A%20%20%20%20public%20void%20%20%20%20subscribe%28Flow.Subscriber%3C%3F%20super%20T%3E%20subscriber%29%3B%20%20%0A%7D%20%20%20%0A%20%20%0Apublic%20static%20interface%20Flow.Subscriber%3CT%3E%20%7B%20%20%0A%20%20%20%20public%20void%20%20%20%20onSubscribe%28Flow.Subscription%20subscription%29%3B%20%20%0A%20%20%20%20public%20void%20%20%20%20onNext%28T%20item%29%20%3B%20%20%0A%20%20%20%20public%20void%20%20%20%20onError%28Throwable%20throwable%29%20%3B%20%20%0A%20%20%20%20public%20void%20%20%20%20onComplete%28%29%20%3B%20%20%0A%7D%20%20%20%0A%20%20%0Apublic%20static%20interface%20Flow.Subscription%20%7B%20%20%0A%20%20%20%20public%20void%20%20%20%20request%28long%20n%29%3B%20%20%0A%20%20%20%20public%20void%20%20%20%20cancel%28%29%20%3B%20%20%0A%7D%20%20%20%0A%20%20%0Apublic%20static%20interface%20Flow.Processor%3CT%2CR%3E%20%20extends%20Flow.Subscriber%3CT%3E%2C%20Flow.Publisher%3CR%3E%20%7B%20%20%0A%7D%20%20%0A%60%60%60%0A%0A%23%23%23%20Subscriber%20callback%0A%0A%uAD6C%uB3C5%uC790%28Subscriber%29%uB294%20%uCF5C%uBC31%uC744%20%uC704%uD574%20%uAC8C%uC2DC%uC790%28Publisher%29%uB97C%20%uAD6C%uB3C5%uD569%uB2C8%uB2E4.%0A%uB370%uC774%uD130%uB294%20%uC694%uCCAD%uD558%uC9C0%20%uC54A%uB294%20%uD55C%20%uAD6C%uB3C5%uC790%uC5D0%uAC8C%20%uD478%uC2DC%uB418%uC9C0%20%uC54A%uC2B5%uB2C8%uB2E4.%20%uBCF4%uD1B5%uC740%20%uC5EC%uB7EC%20%uD56D%uBAA9%uB4E4%uC744%20%uD568%uAED8%20%uC694%uCCAD%uD569%uB2C8%uB2E4.%20%uC8FC%uC5B4%uC9C4%20%uAD6C%uB3C5%uC5D0%20%uB300%uD55C%20%uAD6C%uB3C5%uC790%20%uBA54%uC11C%uB4DC%20%uD638%uCD9C%uC740%20%uC5C4%uACA9%uD558%uAC8C%20%uBA85%uB839%uBC1B%uC2B5%uB2C8%uB2E4.%20%28Subscriber%20method%20invocations%20for%20a%20given%20Subscription%20are%20strictly%20ordered.%29%0A%0A%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC740%20%uAD6C%uB3C5%uC790%uAC00%20%uC0AC%uC6A9%uD560%20%uC218%20%uC788%uB294%20%uC544%uB798%uC758%20%uCF5C%uBC31%uC5D0%20%uBC18%uC751%uD569%uB2C8%uB2E4.%0A%0A%0A1.%20**onSubscribe**%20%3A%20%uC9C0%uC815%uB41C%20Subscription%28%uAD6C%uB3C5%29%uC5D0%20%uB300%uD574%20%uB2E4%uB978%20Subscriber%28%uAD6C%uB3C5%uC790%29%uBA54%uC11C%uB4DC%uB97C%20%uD638%uCD9C%uD558%uAE30%20%uC804%uC5D0%20%uD638%uCD9C%uB418%uB294%20%uBA54%uC11C%uB4DC%uC785%uB2C8%uB2E4.%0A2.%20**onNext**%20%3A%20Subscription%uC758%20%uB2E4%uC74C%20%uD56D%uBAA9%uC73C%uB85C%20%uD638%uCD9C%uB418%uB294%20%uBA54%uC11C%uB4DC%uC785%uB2C8%uB2E4.%0A3.%20**onError**%20%3A%20Publisher%28%uAC8C%uC2DC%uC790%29%20%uB610%uB294%20Subscription%uC5D0%uC11C%20%uBC1C%uC0DD%uD558%uB294%20%uBCF5%uAD6C%20%uD560%20%uC218%20%uC5C6%uB294%20%uC624%uB958%uB85C%20%uC778%uD574%20%uD638%uCD9C%uB41C%20%uBA54%uC11C%uB4DC%uC785%uB2C8%uB2E4.%20%uADF8%20%uD6C4%uC5D0%uB294%20Subscription%uC73C%uB85C%20%uB2E4%uB978%20Subscriber%20%uBA54%uC11C%uB4DC%uAC00%20%uD638%uCD9C%uB418%uC9C0%20%uC54A%uC2B5%uB2C8%uB2E4.%20Publisher%uAC00%20Subscriber%uC5D0%uAC8C%20%uD56D%uBAA9%uC744%20%uBC1C%uD589%uD558%uC9C0%20%uBABB%uD558%uAC8C%20%uD558%uB294%20%uC624%uB958%uAC00%20%uBC1C%uC0DD%uD558%uBA74%20%uD574%uB2F9%20Subscriber%uB294%20onError%uB97C%20%uC218%uC2E0%uD55C%20%uB2E4%uC74C%20%uB354%20%uBA54%uC2DC%uC9C0%uB97C%20%uBC1B%uC9C0%20%uC54A%uC2B5%uB2C8%uB2E4.%0A4.%20**onComplete**%20%3A%20%uC544%uC9C1%20%uC624%uB958%uB85C%20%uC885%uB8CC%uB418%uC9C0%20%uC54A%uC740%20Subscription%uC5D0%20%uB300%uD574%20%uCD94%uAC00%20Subscriber%20%uBA54%uC11C%uB4DC%20%uD638%uCD9C%uC774%20%uBC1C%uC0DD%uD558%uC9C0%20%uC54A%uB294%20%uAC83%uC73C%uB85C%20%uC54C%uB824%uC9C4%20%uD6C4%20Subscription%uC5D0%uC11C%20%uB2E4%uB978%20Subscriber%20%uBA54%uC11C%uB4DC%uB97C%20%uD638%uCD9C%uD558%uC9C0%20%uC54A%uB294%20%uACBD%uC6B0%20%uD638%uCD9C%uB418%uB294%20%uBA54%uC11C%uB4DC%uC785%uB2C8%uB2E4.%20%uB354%20%uC774%uC0C1%uC758%20%uBA54%uC2DC%uC9C0%uAC00%20%uBC1C%uD589%uB418%uC9C0%20%uC54A%uC744%20%uAC83%uC73C%uB85C%20%uC54C%uB824%uC9C4%20%uACBD%uC6B0%2C%20Subscriber%uB294%20onComplete%uB97C%20%uC2E4%uD589%uD569%uB2C8%uB2E4.%0A%0A%23%23%23%20Sample%20Subscriber%0A%0A%60%60%60%0Aimport%20java.util.concurrent.Flow.*%3B%20%20%0A...%20%20%0A%20%20%0Apublic%20class%20MySubscriber%3CT%3E%20implements%20Subscriber%3CT%3E%20%7B%20%20%0A%20%20private%20Subscription%20subscription%3B%20%20%0A%20%20%0A%20%20@Override%20%20%0A%20%20public%20void%20onSubscribe%28Subscription%20subscription%29%20%7B%20%20%0A%20%20%20%20this.subscription%20%3D%20subscription%3B%20%20%0A%20%20%20%20subscription.request%281%29%3B%20//a%20value%20of%20%20Long.MAX_VALUE%20may%20be%20considered%20as%20effectively%20unbounded%20%20%0A%20%20%7D%20%20%0A%20%20%0A%20%20@Override%20%20%0A%20%20public%20void%20onNext%28T%20item%29%20%7B%20%20%0A%20%20%20%20System.out.println%28%22Got%20%3A%20%22%20+%20item%29%3B%20%20%0A%20%20%20%20subscription.request%281%29%3B%20//a%20value%20of%20%20Long.MAX_VALUE%20may%20be%20considered%20as%20effectively%20unbounded%20%20%0A%20%20%7D%20%20%0A%20%20%0A%20%20@Override%20%20%0A%20%20public%20void%20onError%28Throwable%20t%29%20%7B%20%20%0A%20%20%20%20t.printStackTrace%28%29%3B%20%20%0A%20%20%7D%20%20%0A%20%20%0A%20%20@Override%20%20%0A%20%20public%20void%20onComplete%28%29%20%7B%20%20%0A%20%20%20%20System.out.println%28%22Done%22%29%3B%20%20%0A%20%20%7D%20%20%0A%7D%20%20%0A%60%60%60%0A%0A%23%23%23%20%uAC8C%uC2DC%uC790%20%28Publisher%29%0A%uAC8C%uC2DC%uC790%uB294%20%uB4F1%uB85D%20%uB41C%20%uAD6C%uB3C5%uC790%uC5D0%uAC8C%20%uB370%uC774%uD130%20%uD56D%uBAA9%uC758%20%uC2A4%uD2B8%uB9BC%uC744%20%uAC8C%uC2DC%uD569%uB2C8%uB2E4.%20%uC77C%uBC18%uC801%uC73C%uB85C%20Executor%uB97C%20%uC0AC%uC6A9%uD558%uC5EC%20%uD56D%uBAA9%uC744%20%uBE44%uB3D9%uAE30%20%uC801%uC73C%uB85C%20%uAD6C%uB3C5%uC790%uC5D0%uAC8C%20%uAC8C%uC2DC%uD569%uB2C8%uB2E4.%20%0A%uAC8C%uC2DC%uC790%uB294%20%uAC01%20%uAD6C%uB3C5%uC5D0%20%uB300%uD55C%20Subscriber%20%uBA54%uC11C%uB4DC%20%uD638%uCD9C%uC744%20strictly%uD558%uAC8C%20%uC694%uCCAD%uD569%uB2C8%uB2E4.%28Publishers%20ensure%20that%20Subscriber%20method%20invocations%20for%20each%20subscription%20are%20strictly%20ordered.%29%0A%0A%uC544%uB798%uB294%20JDK%uC758%20SubmissionPublisher%uB97C%20%uC0AC%uC6A9%uD558%uC5EC%20%uAD6C%uB3C5%uC790%uC5D0%uAC8C%20%uB370%uC774%uD130%20%uD56D%uBAA9%uC758%20%uC2A4%uD2B8%uB9BC%uC744%20%uAC8C%uC2DC%uD558%uB294%20%uC608%uC2DC%uC785%uB2C8%uB2E4.%0A%0A%60%60%60%0Aimport%20java.util.concurrent.SubmissionPublisher%3B%20%20%0A...%20%20%0A%20%20%20%20//Create%20Publisher%20%20%0A%20%20%20%20SubmissionPublisher%3CString%3E%20publisher%20%3D%20new%20SubmissionPublisher%3C%3E%28%29%3B%20%20%0A%20%20%0A%20%20%20%20//Register%20Subscriber%20%20%0A%20%20%20%20MySubscriber%3CString%3E%20subscriber%20%3D%20new%20MySubscriber%3C%3E%28%29%3B%20%20%0A%20%20%20%20publisher.subscribe%28subscriber%29%3B%20%20%0A%20%20%0A%20%20%20%20//Publish%20items%20%20%0A%20%20%20%20System.out.println%28%22Publishing%20Items...%22%29%3B%20%20%0A%20%20%20%20String%5B%5D%20items%20%3D%20%7B%221%22%2C%20%22x%22%2C%20%222%22%2C%20%22x%22%2C%20%223%22%2C%20%22x%22%7D%3B%20%20%0A%20%20%20%20Arrays.asList%28items%29.stream%28%29.forEach%28i%20-%3E%20publisher.submit%28i%29%29%3B%20%20%0A%20%20%20%20publisher.close%28%29%3B%20%0A%60%60%60%0A%0A%23%23%23%20%uAD6C%uB3C5%20%28The%20Subscription%29%0A%0AFlow.Publisher%uC640%20Flow.Subscriber%uB97C%20%uC5F0%uACB0%uD569%uB2C8%uB2E4.%20%uAD6C%uB3C5%uC790%uB294%20%uC694%uCCAD%uC774%uC788%uC744%20%uB54C%uB9CC%20%uD56D%uBAA9%uC744%20%uC218%uC2E0%uD558%uBA70%20%uAD6C%uB3C5%uC744%20%uD1B5%uD574%20%uC5B8%uC81C%uB4E0%uC9C0%20%uCDE8%uC18C%20%uD560%20%uC218%20%uC788%uC2B5%uB2C8%uB2E4.%0A%0A**Subscription%20Method**%0A%0A1.%20**request**%20%3A%20%uC9C0%uC815%uB41C%20%uC218%uC758%20n%20%uAC1C%20%uD56D%uBAA9%uC744%20%uAD6C%uB3C5%uC5D0%20%uB300%uD55C%20%uD604%uC7AC%20%uCDA9%uC871%uB418%uC9C0%20%uC54A%uC740%20%uC218%uC694%uC5D0%20%uCD94%uAC00%uD569%uB2C8%uB2E4.%0A2.%20**cancel**%20%3A%20%uAD6C%uB3C5%uC790%uAC00%20%uBA54%uC2DC%uC9C0%20%uC218%uC2E0%uC744%20%uC911%uC9C0%uD569%uB2C8%uB2E4.

관련글 더보기

댓글 영역