Різниця між спостережуваним майбутнім, майбутнім і спостережуваним RxJava


194

Я хотів би знати різницю між CompletableFuture, Futureі Observable 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
хотілося б знати, де це по-різному, як це відрізняється в управлінні потоками ?? ПРИКЛАД: Future.get () блокує потік .... як це буде оброблятися в Оглядовому ???
shiv455

2
принаймні, це трохи заплутано для мене ... різниця на високому рівні була б дуже корисною !!
shiv455

Відповіді:


280

Ф'ючерси

Ф'ючерси були представлені на Java 5 (2004). Вони в основному є заповнювачами в результаті операції, яка ще не закінчилася. Як тільки операція закінчиться, заголовок Futureбуде містити цей результат. Наприклад, операція може бути екземпляром Runnable або Callable, який передається в ExecutorService . Подаючий операції може використовувати Futureоб’єкт, щоб перевірити, чи є операціяDone () , або чекати, коли вона закінчиться, використовуючи метод блокування get () .

Приклад:

/**
* 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 були представлені в Java 8 (2014). Насправді вони є еволюцією регулярних ф'ючерсів, натхнених послугами Google « Listenable Futures» , що є частиною бібліотеки 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 . Воно, хіба що набагато потужніше.

Аналогічно до Futures, RxJava може використовуватися для з'єднання купу синхронних або асинхронних дій для створення конвеєра для обробки. На відміну від Futures, які одноразові, RxJava працює на потоках нульових або більше предметів. Включаючи нескінченні потоки з нескінченною кількістю елементів. Це також набагато гнучкіше і потужніше завдяки неймовірно багатому набору операторів .

На відміну від потоків Java 8, RxJava також має механізм зворотного тиску , що дозволяє йому обробляти випадки, коли різні частини обробного трубопроводу працюють в різних потоках , з різною швидкістю .

Мінусом RxJava є те, що, незважаючи на обґрунтовану документацію, бібліотеці є складною мірою вчитися завдяки зміні парадигми. Код Rx також може бути кошмаром для налагодження, особливо якщо задіяно декілька потоків, а ще гірше - якщо потрібен зворотний тиск.

Якщо ви хочете ввійти в нього, на офіційному веб-сайті є ціла сторінка різних навчальних посібників, а також офіційна документація та Javadoc . Ви також можете подивитися деякі відео, наприклад, це, яке дає короткий вступ у Rx, а також розповідає про відмінності між Rx та Futures.

Бонус: реактивні потоки Java 9

Реактивні Потоки Java 9 в аке Flow API є набором інтерфейсів реалізовані з допомогою різних реактивних потоків бібліотек , таких як RxJava 2 , Akka Streams і VertX . Вони дозволяють цим реактивним бібліотекам взаємозв'язуватися, зберігаючи всі важливі тиску.


Було б добре навести приклад коду того, як це робить Rx
Zinan Xing

Отже, використовуючи Реактивні потоки, ми можемо змішувати RxJava, Akka та Vertx в одному додатку?
ІгорГанапольський

1
@IgorGanapolsky Так.
Солод

У CompletableFutures ми використовуємо методи зворотного виклику, ці методи зворотного виклику також блокуються, якщо вихід одного методу є введенням іншого зворотного виклику. Як майбутній блок з викликом Future.get (). Чому кажуть, що Future.get () блокує виклик, тоді як CompletableFutures не блокує. Поясніть, будь ласка,
Діпак

1
@Federico Звичайно. Кожен Futureє заповнювачем місця для одного результату, який може бути або ще не виконаний. Якщо повторити ту саму операцію, ви отримаєте новий Futureекземпляр. RxJava займається потоками результатів, які можуть надійти в будь-який час. Таким чином, ряд операцій може повернути єдине спостережуване RxJava, яке викачає купу результатів. Це трохи схоже на різницю між одним поштовим конвертом та пневматичною трубкою, яка продовжує викачувати пошту.
Солод

21

Я працюю з Rx Java з 0.9, зараз на 1.3.2, і незабаром переходжу на 2.x, я використовую це в приватному проекті, де я вже працюю 8 років.

Я б більше не програмував без цієї бібліотеки. На початку я був скептичним, але це абсолютно інший стан душі, який потрібно створити. Тихіше важко на початку. Я часом дивився на мармур годинами .. lol

Це лише питання практики та справді ознайомлення з потоком (він же договір спостерігачів та спостерігача), як тільки ви потрапите туди, вам буде ненавидіти це робити інакше.

Для мене насправді немає недоліків у цій бібліотеці.

Випадок використання: у мене перегляд монітора, який містить 9 датчиків (процесор, пам'ять, мережа тощо). Під час запуску представлення подання підписується на клас системного монітора, який повертає спостережуваний (інтервал), який містить усі дані за 9 метрів. Це підштовхуватиме кожну секунду новий результат до перегляду (щоб не опитуватись !!!). Цей спостережуваний використовує планову карту, щоб одночасно (асинхронізувати!) Отримання даних з 9 різних джерел і перетягує результат у нову модель, яку ви побачите на onNext ().

Як чорт ви це зробите з ф'ючерсами, комплектаціями тощо ... Удачі! :)

Rx Java вирішує для мене багато проблем у програмуванні і значно полегшує ...

Переваги:

  • Statelss !!! (важливо згадати, найважливіше, можливо)
  • Управління нитками з коробки
  • Побудувати послідовності, які мають власний життєвий цикл
  • Все можна спостерігати, тому ланцюжок простий
  • Менше коду для запису
  • Одномісний баночка на уроці (дуже легкий)
  • Сильно одночасно
  • Більше жодного зворотного дзвінка
  • На основі передплатників (жорсткий договір між споживачем та виробником)
  • Стратегії зворотного тиску (автоматичний вимикач)
  • Чудові обробки та відновлення помилок
  • Дуже приємна документація (мармур <3)
  • Повний контроль
  • Набагато більше ...

Недоліки: - Важко перевірити


13
~ " Я б більше не програмував без цієї бібліотеки. " Так RxJava - це все-таки все-все для всіх програмних проектів?
ІгорГанапольський

Це корисно, навіть якщо у мене немає Потік асинхронних подій?
Мукеш Верма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.