O futuro chegou: Programação concorrente com futures LEONARDO BORGES SENIOR CLOJURE

Similar documents
Completable Future. Srinivasan Raghavan Senior Member of Technical Staff Java Platform Group

Overview of Advanced Java 8 CompletableFuture Features (Part 2)

Introduction to Type Driven Development in Scala

Compositional I/Ο Streams in Scala. Rúnar Bjarnason, Verizon QCon London, March 2016

Using Java CompletionStage in Asynchronous Programming

MONIX TASK LAZY, ASYNC & AWESOME. Alexandru Nedelcu. Software / alexn.org

INSTRUCTIONS TO CANDIDATES

The First Monad Tutorial

CSE341 Section 3. Standard-Library Docs, First-Class Functions, & More

Refactoring mit monadischen Transaktionen. In Java

Overview. Elements of Programming Languages. Advanced constructs. Motivating inner class example

Essential Scala. Six Core Concepts for Learning Scala Noel underscore

Experiences with Scala Across the College-Level Curriculum

Programs as Values Pure Functional Database Access in Scala

Instituto Superior Técnico. First Exam 7/6/2013. Number:

Querying Microsoft SQL Server 2014 (20461)

Asynchronous API with CompletableFuture

SharePoint 2013 Site Collection and Site Administration (55033)

CS Programming Languages: Scala

Purely Functional I/O in Scala

Domain Specific Languages - a user view and an implementation view. does expressiveness imply a compromise on the underlying domain model?

Functional Programming in Scala by Paul Chiusana Rúnar Bjarnason

Those classes I never wrote. The power of recursion schemes applied to data engineering

Enabling and Managing Office 365 (20347)

Functional Programming

EXAM PREPARATION SECTION 10

CS558 Programming Languages

Types Working For You

Learn Sphinx Documentation Documentation

Final Concurrency. Oleg October 27, 2014

OCaml Language Choices CMSC 330: Organization of Programming Languages

Side-effect checking for Scala. Lukas Rytz, Martin Odersky, Adriaan Moors Scala Days 2011

301AA - Advanced Programming

Exercise 1: Graph coloring (10 points)

Introdução e boas práticas em UX Design (Portuguese Edition)

an overview Alceste Scalas Programming languages reading group

Asynchronous API with CompletableFuture

Mastering Advanced Scala

Programming Principles

Introduction to Spark

Sistemas Distribuídos com Redes de Sensores. Noemi Rodriguez

Principles of Programming Languages

Functional Programming

by Mario Fusco Monadic

Python Asynchronous Programming with Salt Stack (tornado, asyncio) and RxPY

Axiomatic Rules. Lecture 18: Axiomatic Semantics & Type Safety. Correctness using Axioms & Rules. Axiomatic Rules. Steps in Proof

CSci 4223 Lecture 12 March 4, 2013 Topics: Lexical scope, dynamic scope, closures

CSE Lecture 7: Polymorphism and generics 16 September Nate Nystrom UTA

Parallel Operations on Collections. Parallel Programming in Scala Viktor Kuncak

Microsoft SharePont Server 2013 for the Site Owner/Power User (55035)

The Rise and Rise of Dataflow in the JavaVerse

Scala - Some essential concepts -

Functional Architecture:

Zte mf667 driver win8. Zte mf667 driver win8.zip

CSCI 3155: Homework Assignment 3

src docs Release Author

More Examples. Lecture 24: More Scala. Higher-Order Functions. Control Structures

INTERFACES IN JAVA. Prof. Chris Jermaine

First Exam/Second Test 19/6/2010

Practically Functional. Daniel Spiewak

Repensando Templates com Cryml. Dalton Pinto

A Formal Model for Direct-style Asynchronous Observables

CS558 Programming Languages

CompSci 220. Programming Methodology 12: Functional Data Structures

CS558 Programming Languages

Generics: Past, Present and Future

CSCI 2041: Lazy Evaluation

// Body of shortestlists starts here y flatmap { case Nil => Nil case x :: xs => findshortest(list(x), xs)

CSCI-GA Final Exam

CPL 2016, week 10. Clojure functional core. Oleg Batrashev. April 11, Institute of Computer Science, Tartu, Estonia

CSE431 Translation of Computer Languages

Acelerando a Manada. Parallel Queries no PostgreSQL

CS558 Programming Languages

Scala Actors. Scalable Multithreading on the JVM. Philipp Haller. Ph.D. candidate Programming Methods Lab EPFL, Lausanne, Switzerland

You ve encountered other ways of signalling errors. For example, if you lookup an unbound key in a hashtable, Java (and Scala) produce nulls:

NADABAS and its Environment

Property Based Testing : Shrinking Risk In Your Code. Amanda Pariveda Solutions Consultant Mined Minds Co-Founder

Compile-Time Code Generation for Embedded Data-Intensive Query Languages

Building a Modular Static Analysis Framework in Scala (Tool Paper)

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

Philipp Wille. Beyond Scala s Standard Library

Generics: Past, Present

Applied Unified Ownership. Capabilities for Sharing Across Threads

Prof. Edwar Saliba Júnior

Unlocking magic of Monads with Java 8

Combining Concurrency Abstractions

Hd video converter factory pro 3. Hd video converter factory pro 3.zip

Imperative Programming 2: Traits

Classical Themes of Computer Science

CSE 130, Fall 2006: Final Examination

JDBC Next A new asynchronous API for connecting to a database

Static Program Analysis Part 1 the TIP language

INTRODUCTION. SHORT INTRODUCTION TO SCALA INGEGNERIA DEL SOFTWARE Università degli Studi di Padova

Introduction to Functional Programming and Haskell. Aden Seaman

Higher-Order Functions

Arne Brüsch Philipp Wille. Pattern Matching Syntax

Big Data Analytics with Apache Spark. Nastaran Fatemi

Advanced Type System Features Tom Schrijvers. Leuven Haskell User Group

List are immutable Lists have recursive structure Lists are homogeneous

Heresies and Dogmas in Software Development

Transcription:

O futuro chegou: Programação concorrente com futures LEONARDO BORGES SENIOR CLOJURE ENGINEER @LEONARDO_BORGES

SOBRE Um pouco sobre mim Senior Clojure Engineer na Atlassian, Sydney Fundador do Grupo de Usuários Clojure de Sydney Autor de Clojure Reactive Programming - http://bit.ly/cljrp * QCon discount code: CRP10

O quê? FUTURES CONCORRÊNCIA ABSTRAÇÃO COMPOSIÇÃO

Futures em Java <= 1.7

FUTURES EM JAVA <= 1.7 static ExecutorService es = Executors.newCachedThreadPool(); static Integer doubler(integer n) { return 2 * n; } static Future<Integer> servicea(integer n) { return es.submit(() -> { Thread.sleep(1000); return n; }); } static Future<Integer> serviceb(integer n) { return es.submit(() -> { Thread.sleep(1500); return Double.valueOf(Math.pow(n, 2)).intValue(); }); } static Future<Integer> servicec(integer n) { return es.submit(() -> { Thread.sleep(2000); return Double.valueOf(Math.pow(n, 3)).intValue(); }); }

FUTURES EM JAVA <= 1.7 Bloqueia a thread Integer doubled = doubler(servicea(10).get()); System.out.println("Couldn't do anything else while the line above was being executed..."); System.out.println("Result: " + serviceb(doubled).get() + " - " + servicec(doubled).get()); Bloqueia a thread Bloqueia a thread

Problemas Desperdício de processamento

Problemas Desperdício de processamento Baixo nível de composição

E no Java 8?

FUTURES NO JAVA 8 final CompletableFuture<Integer> doubled = servicea(10).thenapply(completablefutures::doubler); final CompletableFuture<Integer> resultb = doubled.thencompose(completablefutures::serviceb); final CompletableFuture<Integer> resultc = doubled.thencompose(completablefutures::servicec); CompletableFuture<Void> allfutures = CompletableFuture.allOf(resultB, resultc); allfutures.whencomplete((v, ex) -> { try { System.out.println("Result: " + resultb.get() + " - " + resultc.get()); } catch (Exception e) {} }); System.out.println("Doing other important things...");

FUTURES NO JAVA 8 final CompletableFuture<Integer> doubled = servicea(10).thenapply(completablefutures::doubler); final CompletableFuture<Integer> resultb = doubled.thencompose(completablefutures::serviceb); final CompletableFuture<Integer> resultc = doubled.thencompose(completablefutures::servicec); CompletableFuture<Void> allfutures = CompletableFuture.allOf(resultB, resultc); allfutures.whencomplete((v, ex) -> { try { System.out.println("Result: " + resultb.get() + " - " + resultc.get()); } catch (Exception e) {} }); System.out.println("Doing other important things..."); Não bloqueia a thread

Esses combinadores são familiares?

STREAMS NO JAVA 8 List<Integer> ns = Arrays.asList(1, 2, 3, 4); Function<Integer, Integer> doubler = (i) -> i * 2; System.out.println(ns.stream().map(doubler).collect(Collectors.toList())); // [2, 4, 6, 8] Function<Integer, Stream<? extends Integer>> torange = (i) -> IntStream.range(0, i).boxed(); Stream<Integer> combined = ns.stream().map(doubler).flatmap(torange); System.out.println(combined.collect(Collectors.toList())); // [0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7]

Streams vs Futures Stream<R> map(function<? super T,? extends R> mapper) { } Stream<R> flatmap(function<? super T,? extends Stream<? extends R>> mapper) { } CompletableFuture<U> thenapply(function<? super T,? extends U> fn) { } CompletableFuture<U> thencompose(function<? super T,? extends CompletionStage<U>> fn) { }

Streams vs Futures Stream<R> map(function<? super T,? extends R> mapper) { } Stream<R> flatmap(function<? super T,? extends Stream<? extends R>> mapper) { } CompletableFuture<U> thenapply (Function<? super T,? extends U> fn) { } CompletableFuture<U> thencompose(function<? super T,? extends CompletionStage<U>> fn) { }

E se quisermos escrever funções que funcionem com Streams e Futures?

SEQUENCING FUTURES CompletableFuture<Collection<Integer>> result = // java.util.concurrent.completablefuture[10, 100, 1000] sequence(servicea(10), serviceb(10), servicec(10));

SEQUENCING FUTURES static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); }

SEQUENCING FUTURES static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); }

SEQUENCING FUTURES static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); }

SEQUENCING FUTURES static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); }

SEQUENCING FUTURES static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); }

SEQUENCING STREAMS Stream<Integer> s1 = Arrays.asList(1).stream(); Stream<Integer> s2 = Arrays.asList(2).stream(); Stream<Integer> s3 = Arrays.asList(3).stream(); sequences(s1, s2, s3) // [[1, 2, 3]]

SEQUENCING STREAMS static <A> Stream<Stream<A>> sequences(stream<a>... cfs) { return Arrays.asList(cfs).stream().reduce( Stream.of(Stream.empty()), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, Stream.of(x)))), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, x)))); }

SEQUENCING STREAMS static <A> Stream<Stream<A>> sequences(stream<a>... cfs) { return Arrays.asList(cfs).stream().reduce( Stream.of(Stream.empty()), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, Stream.of(x)))), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, x)))); }

SEQUENCING STREAMS static <A> Stream<Stream<A>> sequences(stream<a>... cfs) { return Arrays.asList(cfs).stream().reduce( Stream.of(Stream.empty()), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, Stream.of(x)))), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, x)))); }

SEQUENCING STREAMS static <A> Stream<Stream<A>> sequences(stream<a>... cfs) { return Arrays.asList(cfs).stream().reduce( Stream.of(Stream.empty()), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, Stream.of(x)))), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, x)))); }

Perceberam alguma semelhança?

FUTURES VS STREAMS static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); } static <A> Stream<Stream<A>> sequences(stream<a>... cfs) { return Arrays.asList(cfs).stream().reduce( Stream.of(Stream.empty()), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, Stream.of(x)))), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, x)))); }

FUTURES VS STREAMS static <A> CompletableFuture<Collection<A>> sequence(completablefuture<a>... cfs) { return Arrays.asList(cfs).stream().reduce( CompletableFuture.completedFuture(new ArrayList<>()), (acc, future) -> acc.thencompose((xs) -> future.thenapply((x) -> { xs.add(x); return xs; })), (a, b) -> a.thencompose((xs) -> b.thenapply((ys) -> { xs.addall(ys); return xs; }))); } static <A> Stream<Stream<A>> sequences(stream<a>... cfs) { return Arrays.asList(cfs).stream().reduce( Stream.of(Stream.empty()), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, Stream.of(x)))), (acc, coll) -> acc.flatmap((xs) -> coll.map((x) -> Stream.concat(xs, x)))); }

FlatMappable

FLATMAPPABLE <M extends FlatMappable, A> M<List<A>> sequence(m<a>... ma) { }

Chegando no limite do sistema de tipos Java não suporta tipos de alta espécie (higher kinded types) Tipos de alta espécie são indispensáveis ao se implementar tais abstrações

Colocando nome nos bois

FlatMappable se chama Monad trait Monad[F[_]] { def point[a](a: => A): F[A] def bind[a, B](a: F[A])(f: A => F[B]): F[B] def map[a, B](a: F[A])(f: A => B): F[B] = bind(a)(b => point(f(b))) }

FlatMappable se chama Monad trait Monad[F[_]] { Tipos de alta espécie em ação def point[a](a: => A): F[A] def bind[a, B](a: F[A])(f: A => F[B]): F[B] def map[a, B](a: F[A])(f: A => B): F[B] = bind(a)(b => point(f(b))) }

MONADS EM SCALA O Monad de Futures implicit def FutureMonad: Monad[Future] = new Monad[Future] { def point[a](a: => A) = Future.successful(a) } def bind[a, B](a: Future[A])(f: A => Future[B]): Future[B] = a flatmap f

MONADS EM SCALA O Monad de Listas implicit def ListMonad: Monad[List] = new Monad[List] { def point[a](a: => A) = List(a) def bind[a, B](a: List[A])(f: A => List[B]): List[B] = a flatmap f }

MONADS EM SCALA Implementando sequence def sequence[m[_] : Monad, A](ma: List[M[A]]): M[List[A]] = { ma.foldleft(monad[m].point(list(): List[A]))((acc, m) => acc.flatmap((xs) => m.map((x) => xs :+ x)) ) }

Being abstract is something profoundly different from being vague The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise. EDSGER W. DIJKSTRA

MONADS EM SCALA Sequencing val resultf: Future[List[Integer]] = sequence(list(servicea(10), serviceb(10), servicec(10))) println(await.result(resultf, Duration(2, "seconds"))) // List(10, 100, 1000) val resultl: List[List[Int]] = sequence(list(list(1,2,3), List(4,5,6), List(7,8,9))) println(resultl) // List(List(1, 4, 7), List(2, 4, 7), List(3, 4, 7), List(1, 5, 7),...)

Demais! O quê mais podemos fazer??

Folding

FOLDING List(2, 3, 4).reduce(_+_) //9

FOLDING List(2, 3, 4).reduce(_+_) //9 val intfutures = List(Future.successful(1), Future.successful(2), Future.successful(3)) val result: Future[Int] = sequence(intfurures).map((x) => x.reduce(_ + _)) // Future[9]

Existe algo em comum?

Introduzindo Foldable trait Foldable[F[_]] { self => def fold[m: Monoid](t: F[M]): M =??? }

Introduzindo Monoids trait Monoid[F] { self => def zero: F def append(f1: F, f2: => F): F }

Introduzindo Monoids: Ints implicit def intmonoid: Monoid[Int] = new Monoid[Int] { def zero: Int = 0 def append(f1: Int, f2: => Int): Int = f1 + f2 }

Introduzindo Monoids: Ints implicit def intmonoid: Monoid[Int] = new Monoid[Int] { def zero: Int = 0 def append(f1: Int, f2: => Int): Int = f1 + f2 } Foldable[List].fold(List(2, 3, 4))) //9

Introduzindo Monoids: Futures

Introduzindo Monoids: Futures implicit def futurefreemonoid[a] = new Monoid[Future[List[A]]] { def zero: Future[List[A]] = Future.successful(List()) def append(f1: Future[List[A]], f2: => Future[List[A]]) = for { a1 <- f1 a2 <- f2 } yield a1 ++ a2 }

Introduzindo Monoids: Futures implicit def futurefreemonoid[a] = new Monoid[Future[List[A]]] { def zero: Future[List[A]] = Future.successful(List()) def append(f1: Future[List[A]], f2: => Future[List[A]]) = for { a1 <- f1 a2 <- f2 } yield a1 ++ a2 } Foldable[List].fold(List(Future.successful(2), Future.successful(3), Future.successful(4))) // Future[9]

Monad, Foldable e Monoid são apenas o começo

Em Scala, muitas delas já foram implementadas em Scalaz

A Teoria das Categorias pode ter um impacto grande na criação de bibliotecas

Being abstract is something profoundly different from being vague The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise. EDSGER W. DIJKSTRA

Referências Clojure Reactive Programming - http://bit.ly/cljrp Java 8 CompletableFuture - http://bit.ly/j8future Java 8 Streams - http://bit.ly/j8stream Category Theory - http://amzn.to/1nfl08u Free Monoids - http://en.wikipedia.org/wiki/free_monoid Scalaz - https://github.com/scalaz/scalaz Fluokitten (Clojure) - https://github.com/uncomplicate/fluokitten

Obrigado! Q&A LEONARDO BORGES SENIOR CLOJURE DEVELOPER @LEONARDO_BORGES

We are hiring! LEONARDO BORGES SENIOR CLOJURE DEVELOPER @LEONARDO_BORGES