Handling of unexpected cases of RxJava concurrency

Source: Internet
Author: User
Tags joins

Rx tries to avoid state leaks to scenarios outside of the data stream. But some things have their own state. For example, the server can be online and offline, the phone can access WiFi, button was pressed and so on. In Rx China, we see these events over a period of time and call them windows. Other events occurring within this window may require special handling. For example, when mobile phones are used to surf the internet, the priority of the network request is lowered to avoid the sky-high traffic charges.

Note: The above paragraph is estimated to be translated, a bit of a statement does not pass. More Reference website:
Http://www.introtorx.com/Content/v1.0.10621.0/17_SequencesOfCoincidence.html#SequencesOfCoincidence

Windows window

The buffer function can cache multiple data and launch it as a whole. The window operator function and buffer have a one-to-a relationship. The difference is that window does not return the cached data as a whole. Instead, the cached data is returned as a new Observable data stream. So when the source Observable has data emitted, the data is immediately emitted into the Observable of the window return.

You can see the difference between the two:

window:

If you do not already know the buffer, it is recommended that you go to the previous chapter and look at buffer. The function form of buffer and window is the same, the function is very similar, and easy to understand. Buffer can use window to implement its function:

source.buffer(...) // 和下面的是一样的功能source.window(...).flatMap(w -> w.toList())
Window by Count

The number can be limited within the window. When the data emitted by the window reaches the specified number, the Observable of the current window ends and a new window is opened.

Like buffer, using window (int count, int skip) can also skip data or overlap with data.

Observable    .merge(        Observable.range(05)            .window(3,1))    .subscribe(System.out::println);

Results:

011222333444

You can see that when there is data overlap, more than one Observable will return the same data, you can change the result output form, easy to see:

Observable.range(05)    .window(31)    .flatMap(o -> o.toList())    .subscribe(System.out::println);

Results:

[012][123][234][34][4]

This allows you to see that the window and buffer are very similar.

Window by Time

You can also specify the window's length of time:

publicfinalwindow(longlong timeshift, java.util.concurrent.TimeUnit unit)
Observable.interval(100, TimeUnit.MILLISECONDS)    .take(5)    .window(250100, TimeUnit.MILLISECONDS)    .flatMap(o -> o.toList())    .subscribe(System.out::println);

Results:

[01][012][123][234][34][4]

In the example above, a new window starts every 100ms, and each window lasts 250ms. The first window starts at 0MS and captures the data [0, 1] (0 is emitted at 100ms).

Window with Signal

It is also possible to use another signal observable as a signal to end the window.


Signal Observable can also pass events directly to each other.

The following is an overlapping window implemented using signal Observable:

Observable.interval(100, TimeUnit.MILLISECONDS)    .take(5)    .window(        Observable.interval(100, TimeUnit.MILLISECONDS),        o -> Observable.timer(250, TimeUnit.MILLISECONDS))    .flatMap(o -> o.toList())    .subscribe(System.out::println);

Results:

[12][23][34][4][]

Note that the number 0 above is not captured because both the source Observable and the signal Observable occur at the same time, but this is not the case in the actual operation. So when the signal observable, the number 0 was fired.

Join

Join can combine data from two data streams. The ZIP function combines data according to the order in which the data is emitted. Joins can be combined according to time.

public final  <tright,tleftduration,trightduration,r ;  Observable <r ;  join (Observabletright ;  right, Func1< t,observable  <tleftduration ;  > Leftdurationselector, Func1<tright,observable  < trightduration ;  > Rightdurationselector, FUNC2 <t,tright,r ;  resultselector)   

The two Observable of a join combination are called Left and right. The function above is not static, and the observable that calls the function is left. The Leftdurationselector and rightdurationselector in the parameter use the left and right emitted data as parameters, and then return a Observable that defines the interval, similar to the last overloaded function of window. This interval is used to select the data that is emitted from the inside and combine it. The data inside is called resultselector as a parameter, and then a combined data is returned. The combined data is then emitted by the Observable returned by the join.

Joins are more difficult to understand and powerful if you choose to combine data. When there is data emitted in the source Observable, a time window for that data is started. The time interval that corresponds to when the data window ends. When the time window is not over, the data emitted by another Observable is combined with the current data. The left and right data streams are handled the same way, so to simplify the introduction, we assume that only one source Observable has a time window.

In the following example, the left observable data flow never ends and the right observable time window is 0.

Observable<string> left = Observable. Interval( -, Timeunit. MILLISECONDS). Map(I-"L"+ i);observable<string> right = Observable. Interval( $, Timeunit. MILLISECONDS). Map(I-"R"+ i);Left. Join(Right, I-Observable. Never(), I-Observable. Timer(0, Timeunit. MILLISECONDS), (L,r)-L +" - "+ R). Take(Ten). Subscribe(System. out::p rintln);

Results:

R0R0R1R1R1R1R2R2R2R2

Since the left Observable time window is permanent, this means that each emitted data on the left will be combined with the data on the right. When the right data is emitted more slowly than the left one. So when the data on the left emits two of the same data that corresponds to the right. Then the right-hand launch of the next data opens up a new time window on the right, and then the data is combined from the beginning data and the new window in the right.

The following example sets the interval for both left and right source Observable to 100ms, and then sets the left time window to 150ms:

Observable<string> left = Observable. Interval( -, Timeunit. MILLISECONDS). Map(I-"L"+ i);observable<string> right = Observable. Interval( -, Timeunit. MILLISECONDS). Map(I-"R"+ i);Left. Join(Right, I-Observable. Timer( Max, Timeunit. MILLISECONDS), I-Observable. Timer(0, Timeunit. MILLISECONDS), (L,r)-L +" - "+ R). Take(Ten). Subscribe(System. out::p rintln);

Results:

R0R1R1R2R2R3R3R4R4R5

The data is emitted at the same time, so the first window is started, and then the combined data is "l0–r0". Then left the time window to continue, and the right to launch new data R1 then the right of the data R1 and the left side of the L0 combination "L0–r1", and then after 50ms, the left of the time window ended, open the next time window, the result is "L1–R1". Keep repeating.

Two data streams have a time window. Each value in each data flow is combined as follows:

    • If the old Data Time window is not finished, then the combination of each old data in the other data stream
    • If the time window for the current data is not finished, then each new data combination in the other data stream.
GroupJoin

As soon as a combined data is detected, the join invokes resultselector with two data and emits the returned data. And the GroupJoin has different functions:

publicfinal <T2,D1,D2,R> Observable<R> groupJoin(    Observable<T2> right,    superextends Observable<D1>> leftDuration,    superextends Observable<D2>> rightDuration,    supersuperextends R> resultSelector)

In addition to resultselector, other parameters are the same as the join function. This resultselector gets a data from the data stream on the left and gets a Observable from the data stream on the right. This Observable will launch all data paired with the data on the left. The pairing in GroupJoin is symmetrical as a join, but the result is not the same. Resultselect can be implemented as a groupedobservable, the left side of the data as a key, and the right to the data emitted.

Also using the first join example, the time window of the data flow on the left is not closed again:

Observable<string> left = Observable. Interval( -, Timeunit. MILLISECONDS). Map(I-"L"+ i). Take(6);observable<string> right = Observable. Interval( $, Timeunit. MILLISECONDS). Map(I-"R"+ i). Take(3);Left. GroupJoin(Right, I-Observable. Never(), I-Observable. Timer(0, Timeunit. MILLISECONDS), (L, RS), RS. ToList(). Subscribe(List--System. out. println(L +": "+ list)). Subscribe();

Results:

L0: [R0R1R2]L1: [R0R1R2]L2: [R1R2]L3: [R1R2]L4: [R2]L5: [R2]

The sample data pairing in the above example and Jion is the same, except that resultselector does not produce the same results as the output.

The functions of jion can be implemented using GroupJoin and FLATMAP:

.join(    right,    leftDuration    rightDuration,    (l,r) -> joinResultSelector(l,r))// 和下面的一样.groupJoin(    right,    leftDuration    rightDuration,    (l, rs) -> rs.map(r -> joinResultSelector(l,r))).flatMap(i -> i)

GroupJoin can also be implemented through joins and GroupBy. There is this implementation in the sample code, which is interesting to look at.

This article is from the cloud in the Thousand peaks http://blog.chengyunfeng.com/?p=980

Handling of unexpected cases of RxJava concurrency

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.