ความแตกต่างระหว่างอนาคตที่สมบูรณ์ในอนาคตและ RxJava ที่สังเกตได้


194

ผมอยากจะทราบความแตกต่างระหว่าง CompletableFuture, และFutureObservable RxJava

สิ่งที่ฉันรู้คือทั้งหมดนั้นไม่ตรงกัน แต่

Future.get() บล็อกเธรด

CompletableFuture ให้วิธีการโทรกลับ

RxJava Observable--- คล้ายCompletableFutureกับผลประโยชน์อื่น ๆ (ไม่แน่ใจ)

ตัวอย่างเช่น: หากลูกค้าต้องการใช้บริการหลายสายและเมื่อเราใช้Futures(Java) Future.get()จะถูกดำเนินการตามลำดับ ... ต้องการทราบว่า RxJava ดีกว่าได้อย่างไร

และเอกสารประกอบhttp://reactivex.io/intro.htmlกล่าว

เป็นการยากที่จะใช้ฟิวเจอร์สในการเขียนขั้นตอนการดำเนินการแบบอะซิงโครนัสตามเงื่อนไขอย่างเหมาะสมที่สุด (หรือเป็นไปไม่ได้เนื่องจากเวลาแฝงของแต่ละคำขอแตกต่างกันที่รันไทม์) สามารถทำสิ่งนี้ได้ แต่มันจะซับซ้อนอย่างรวดเร็ว (และทำให้เกิดข้อผิดพลาดได้ง่าย) หรือบล็อกอยู่บน Future.get () ก่อนกำหนดซึ่งจะกำจัดข้อดีของการประมวลผลแบบอะซิงโครนัส

สนใจจริงๆที่จะรู้วิธีRxJavaแก้ปัญหานี้ ฉันพบว่ามันยากที่จะเข้าใจจากเอกสาร


คุณอ่านเอกสารสำหรับแต่ละเล่มแล้วหรือยัง? ฉันไม่คุ้นเคยกับ RxJava โดยสิ้นเชิง แต่เอกสารปรากฏขึ้นอย่างละเอียดมาก ดูเหมือนจะไม่สามารถเปรียบเทียบได้กับฟิวเจอร์สทั้งสองโดยเฉพาะ
FThompson

ฉันได้ผ่านมาแล้ว แต่ไม่สามารถรับความแตกต่างจากอนาคตของ Java ได้ ... แก้ไขฉันถ้าฉันผิด
shiv455

สังเกตุคล้ายกับอนาคตอย่างไร
FThompson

2
ต้องการทราบว่ามันแตกต่างกันอย่างไรมันแตกต่างกันในการจัดการเธรดหรือไม่? EX: Future.get () บล็อกเธรด .... วิธีจัดการใน Observable ???
shiv455

2
อย่างน้อยมันก็สับสนสำหรับฉัน ... ความแตกต่างในระดับสูงจะเป็นประโยชน์จริง ๆ !!
shiv455

คำตอบ:


280

ฟิวเจอร์ส

ฟิวเจอร์ถูกนำมาใช้ใน Java 5 (2004) โดยทั่วไปแล้วจะเป็นตัวแทนสำหรับผลลัพธ์ของการดำเนินการที่ยังไม่เสร็จ เมื่อการดำเนินการเสร็จสิ้นFutureจะมีผลลัพธ์นั้น ยกตัวอย่างเช่นการดำเนินการอาจจะเป็นRunnableหรือCallableอินสแตนซ์ที่จะถูกส่งไปยังExecutorService ผู้ส่งของการดำเนินการสามารถใช้Futureวัตถุที่จะตรวจสอบว่าการดำเนินการisDone ()หรือรอให้เสร็จสิ้นการใช้บล็อกได้รับ ()วิธีการ

ตัวอย่าง:

/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 1;
    }

}

public static void main(String[] args) throws Exception{
    ExecutorService exec = Executors.newSingleThreadExecutor();
    Future<Integer> f = exec.submit(new MyCallable());

    System.out.println(f.isDone()); //False

    System.out.println(f.get()); //Waits until the task is done, then prints 1
}

CompletableFutures

CompletableFuturesเปิดตัวใน Java 8 (2014) อันที่จริงแล้วมันเป็นวิวัฒนาการของฟิวเจอร์สปกติซึ่งได้รับแรงบันดาลใจจากListenable Futuresของ Google ซึ่งเป็นส่วนหนึ่งของห้องสมุดGuava พวกเขาเป็นฟิวเจอร์สที่ช่วยให้คุณสามารถรวมภารกิจเข้าด้วยกันในห่วงโซ่ คุณสามารถใช้มันเพื่อบอกเธรดผู้ปฏิบัติงานเพื่อ "ทำงานบางอย่าง X และเมื่อเสร็จแล้วให้ทำสิ่งอื่นโดยใช้ผลลัพธ์ของ X" การใช้ CompletableFutures คุณสามารถทำบางสิ่งกับผลลัพธ์ของการดำเนินการได้โดยไม่ต้องบล็อกเธรดเพื่อรอผลลัพธ์ นี่คือตัวอย่างง่ายๆ:

/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {

    @Override
    public Integer get() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //Do nothing
        }
        return 1;
    }
}

/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {

    @Override
    public Integer apply(Integer x) {
        return x + 1;
    }
}

public static void main(String[] args) throws Exception {
    ExecutorService exec = Executors.newSingleThreadExecutor();
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
    System.out.println(f.isDone()); // False
    CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
    System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}

RxJava

RxJavaเป็นห้องสมุดทั้งหมดสำหรับการเขียนโปรแกรมเชิงโต้ตอบที่สร้างขึ้นที่ Netflix ได้อย่างรวดเร็วก็จะปรากฏจะคล้ายกับลำธาร Java 8 มันยกเว้นว่ามันจะมีประสิทธิภาพมากกว่า

ในทำนองเดียวกันกับฟิวเจอร์ส RxJava สามารถใช้เพื่อรวมสตริงของการกระทำแบบซิงโครนัสหรือแบบอะซิงโครนัสเข้าด้วยกันเพื่อสร้างขั้นตอนการประมวลผล ต่างจาก Futures ซึ่งเป็นแบบใช้ครั้งเดียว RxJava ทำงานบนสตรีมของรายการที่เป็นศูนย์หรือมากกว่า การรวมสตรีมที่ไม่มีที่สิ้นสุดด้วยจำนวนรายการที่ไม่สิ้นสุด นอกจากนี้ยังขอบคุณที่มีความยืดหยุ่นมากขึ้นและมีประสิทธิภาพในการอุดมไปด้วยอย่างไม่น่าเชื่อการตั้งค่าของผู้ประกอบการ

ซึ่งแตกต่างจากลำธาร Java 8, RxJava ยังมีbackpressureกลไกที่ช่วยให้สามารถจัดการกับกรณีที่ชิ้นส่วนที่แตกต่างกันของท่อประมวลผลการดำเนินงานในหัวข้อที่แตกต่างกันในอัตราที่แตกต่างกัน

ข้อเสียของ RxJava คือแม้จะมีเอกสารที่เป็นของแข็ง แต่ก็เป็นห้องสมุดที่ท้าทายในการเรียนรู้เนื่องจากการเปลี่ยนกระบวนทัศน์ที่เกี่ยวข้อง รหัส Rx อาจเป็นฝันร้ายสำหรับการดีบักโดยเฉพาะหากมีหลายเธรดที่เกี่ยวข้อง

หากคุณต้องการที่จะได้รับในนั้นมีทั้งหน้าของบทเรียนต่างๆในเว็บไซต์อย่างเป็นทางการรวมทั้งอย่างเป็นทางการเอกสารและJavadoc นอกจากนี้คุณยังสามารถดูวิดีโอบางส่วนเช่นวิดีโอนี้ซึ่งให้คำแนะนำสั้น ๆ เกี่ยวกับ Rx และพูดคุยเกี่ยวกับความแตกต่างระหว่าง Rx และฟิวเจอร์ส

โบนัส: Java 9 Reactive Streams

Java 9 ปฏิกิริยา Streams aka ไหล APIเป็นชุดของการเชื่อมต่อต่างๆที่ดำเนินการโดยปฏิกิริยาลำธารห้องสมุดเช่นRxJava 2 , Akka ลำธารและVertx พวกเขาอนุญาตให้ไลบรารีปฏิกิริยาเหล่านี้เชื่อมต่อระหว่างกันในขณะที่รักษาแรงกดดันด้านหลังที่สำคัญทั้งหมดไว้


คงจะดีถ้าให้โค้ดตัวอย่างว่า Rx ทำเช่นนี้ได้อย่างไร
Zinan Xing

ดังนั้นเมื่อใช้ Reactive Streams เราสามารถผสม RxJava, Akka และ Vertx ในแอปพลิเคชันเดียวได้หรือไม่
IgorGanapolsky

1
@IgorGanapolsky ใช่
Malt

ใน CompletableFutures เราใช้วิธีการโทรกลับวิธีการโทรกลับเหล่านี้จะปิดกั้นหากเอาต์พุตของวิธีหนึ่งเป็นอินพุตของการโทรกลับอื่น ๆ เป็นบล็อกในอนาคตที่มีการโทร Future.get () ทำไมมีการกล่าวว่า Future.get () กำลังบล็อกการโทรในขณะที่ CompletableFutures ไม่ได้บล็อก โปรดอธิบาย
Deepak

1
@ เฟเดริโกชัวร์ แต่ละรายการFutureเป็นตัวยึดตำแหน่งสำหรับผลลัพธ์เดียวที่อาจหรืออาจยังไม่เสร็จสมบูรณ์ หากคุณทำการดำเนินการเดิมอีกครั้งคุณจะได้รับFutureอินสแตนซ์ใหม่ RxJava เกี่ยวข้องกับกระแสข้อมูลผลลัพธ์ซึ่งสามารถมาได้ตลอดเวลา ชุดของการดำเนินการสามารถส่งคืน RxJava ที่สามารถสังเกตได้ซึ่งจะส่งผลลัพธ์ออกมาจำนวนมาก มันเหมือนกับความแตกต่างระหว่างซองไปรษณีย์เดียวกับท่อลมที่สูบออกไปเรื่อย ๆ
มอลต์

21

ฉันทำงานกับ Rx Java มาตั้งแต่ 0.9 ตอนนี้อยู่ที่ 1.3.2 และเร็ว ๆ นี้ที่จะย้ายไปที่ 2.x ฉันใช้สิ่งนี้ในโครงการส่วนตัวที่ฉันทำงานมา 8 ปีแล้ว

ฉันจะไม่เขียนโปรแกรมหากไม่มีไลบรารี่นี้อีกต่อไป ในตอนแรกฉันถูกสงสัย แต่มันเป็นสภาวะที่สมบูรณ์ของจิตใจที่คุณต้องสร้าง เงียบยากในการเริ่มต้น บางครั้งฉันก็มองหินอ่อนเป็นเวลาหลายชั่วโมง .. lol

มันเป็นเรื่องของการฝึกฝนและทำความรู้จักกับการไหล (หรือที่รู้จักกันในนามของนักสังเกตการณ์และผู้สังเกตการณ์) เมื่อคุณไปถึงที่นั่นคุณจะเกลียดที่จะทำอย่างอื่น

สำหรับฉันมันไม่มีข้อเสียจริง ๆ ในห้องสมุดนั่น

กรณีการใช้งาน: ฉันมีมุมมองจอภาพที่มี 9 เกจ (cpu, mem, เครือข่าย ฯลฯ ... ) เมื่อเริ่มต้นมุมมองมุมมองจะสมัครรับข้อมูลตัวเองไปยังคลาสการตรวจสอบระบบที่ส่งกลับค่าที่สังเกตได้ (ช่วงเวลา) ที่มีข้อมูลทั้งหมดสำหรับ 9 เมตร มันจะผลักดันผลลัพธ์ใหม่ให้กับแต่ละวินาทีในมุมมอง (ดังนั้นอย่าสำรวจ !!!) สิ่งที่สังเกตได้นั้นใช้ flatmap เพื่อดึงข้อมูลจากแหล่งที่แตกต่างกัน 9 แหล่งและบีบอัดผลลัพธ์ลงในโมเดลใหม่ที่มุมมองของคุณจะได้รับจาก onNext ()

คุณจะทำยังไงกับฟิวเจอร์สสำเร็จสมบูรณ์ ฯลฯ ... ขอให้โชคดี! :)

Rx Java แก้ปัญหาต่าง ๆ ในการเขียนโปรแกรมให้ฉันและทำให้ง่ายขึ้นมาก ...

ข้อดี:

  • Statelss !!! (สิ่งสำคัญที่ต้องพูดถึงอาจสำคัญที่สุด)
  • การจัดการเธรดออกจากกล่อง
  • สร้างลำดับที่มีวงจรชีวิตของตัวเอง
  • ทุกอย่างเป็นสิ่งที่สังเกตได้ง่าย
  • รหัสน้อยที่จะเขียน
  • โถเดี่ยวบน classpath (เบามาก)
  • พร้อมกันสูง
  • ไม่มีนรกโทรกลับอีกต่อไป
  • สมาชิกตาม (สัญญาแน่นระหว่างผู้บริโภคและผู้ผลิต)
  • กลยุทธ์แรงดันย้อนกลับ (เบรกเกอร์เหมือน)
  • การจัดการและกู้คืนข้อผิดพลาดที่ยอดเยี่ยม
  • เอกสารที่ดีมาก (หินอ่อน <3)
  • การควบคุมที่สมบูรณ์
  • อื่น ๆ อีกมากมาย ...

ข้อเสีย: - ยากที่จะทดสอบ


13
~ " ฉันจะไม่เขียนโปรแกรมหากไม่มีไลบรารี่นี้อีกต่อไปแล้ว " ดังนั้น RxJava จึงเป็นจุดจบของโครงการซอฟต์แวร์ทั้งหมดใช่ไหม
IgorGanapolsky

มันจะมีประโยชน์หรือไม่แม้ว่าฉันจะไม่มีกระแสของเหตุการณ์อะซิงโครนัส
Mukesh Verma
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.