[concurrency-interest] CompletableFuture in Java 8

√iktor Ҡlang viktor.klang at gmail.com
Fri Dec 12 17:04:36 EST 2014

Hi Thurston,

On Fri, Dec 12, 2014 at 9:44 PM, thurstonn <thurston at nomagicsoftware.com>

> √iktor Ҡlang wrote
> >> Hello Viktor,
> >>
> >> Although this may seem a digression, I'm curious whether you object to
> >> something like Collectors#toList() in j.u.stream?
> >>
> >> Because this facilitates (I wouldn't say encourages) code like the
> >> following:
> >>
> >>
> >> List
> > <T>
> >  l1 = . . .
> >> List
> > <T>
> >  l2 = l1.stream().filter(...).collect(toList())
> >>
> >> List
> > <T>
> >  l3 = l2.stream().map(...).collect(toList())
> >>
> >> for (T : l3)
> >>   do something
> >>
> >> Now, we can all agree that the code above is awful, even wrong, but is
> >> it's
> >> possibility (well, probably more than possibility - I've actually seen
> >> such
> >> code) enough to warrant the exclusion of Collectors.toList()?
> >>
> >
> > At least that code doesn't impact liveness of the system. (well, you can
> > still OOME, but you can do that by allocating an array, so that's not
> > really the same)
> Frankly, I don't understand "impact liveness of the system" - the classical
> definition of liveness is "a guarantee that each thread (process, etc) will
> *eventually* succeed" -
> Doesn't a (hypothetical) CompletionStage#get() offer the same liveness
> guarantee as any of the "terminal operations" on Stream?

I misunderstood what you tried to convey in your example, to me it just
looked like wasteful copying.

So to answer (sort of) your question: I am not a fan of the blocking
terminal operations in Stream and would have preferred to only expose async
terminal operations (returning a CompletionStage). Perhaps we can get
`async` versions of them for Java 9? (I assume deprecating the blocking
ones is going to be a hard sell)

> In fact, IFAICT, Stream#collect() can indeed block (probably does for
> parallel streams), that's an implementation detail, and doesn't really
> change the semantics of the program (of course the JVM could crash, or the
> scheduler might never again schedule a thread, etc., but let's hand-wave
> those away)

There's already been reports of deadlocks when nesting terminal operations
for parallel streams.

> What I was really asking (not very well in retrospect), is if you wouldn't
> prefer the Stream api to have its terminal operations return
> CompletionStage
> (or some rump)?, i.e. your objection isn't restricted to just narrow
> questions of blocking/not-blocking, but mixing "reactive"-style programming
> (or as you termed it "async monadic-style programming") with imperative
> style

Evidently I should have read your email before starting to reply, but "yes"

> √iktor Ҡlang wrote
> >> Of course the issue isn't exactly one of "encouraging blocking" (unless
> >> the
> >> streams were parallel) . . .
> >>
> >> I guess I think that "discouragement by difficulty" in API design more
> >> often
> >> than not leads to grief (which is not to say that I've never done it)
> >>
> >
> > Do you have any example?
> Not sure what you're asking here -- but (assuming there was no
> #toCompletableFuture()), your code on implementing a "blocking get" on a
> CompletionStage is a prime example; that's certainly not the only way (as
> an
> aside I played around with a cursory alternative approach and soon got
> myself into trouble).

Tongue in cheek but you want yet another way of doing blocking because all
the other ones were not good enough? :-)

> The point being, that if we can agree that many developers will want it (I
> think that's undeniable),

That raises the question: should API be create on a "want" basis or on a
"need" basis?

 The good thing about "Await" is that it is easy to define rules to fail
the build if someone calls it,
but given how many have gotten themselves into problems by using Await, I'd
probably not add it if I could do it all over again.

> it's better to leave the implementation
> encapsulated in the implementing CompletionStage class than have the
> numerous adhoc approaches that inevitably result.
> And put in the necessary admonitions in the JavaDoc

I'd have to disagree., and I am sure you aren't surprised by that!

The least damaging approach I think would be to -not- have blocking in the
API and add documentation on how to achieve blocking but show how to avoid
blocking, and put appropriate warnings all around the blocking approach.
This prevents it from showing up in IntelliSense—and thus encourages the
reading of the documentation, and hopefully understanding why it is most
likely a bad idea, and also how to "do the right thing".

> --
> View this message in context:
> http://jsr166-concurrency.10961.n7.nabble.com/CompletableFuture-in-Java-8-tp11414p11626.html
> Sent from the JSR166 Concurrency mailing list archive at Nabble.com.
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20141212/7d69836b/attachment.html>

More information about the Concurrency-interest mailing list