Top Banner
Programação paralela. Future e Stream Docente: MSc. Angel Alberto Vazquez Sánchez ISUTIC 2017
35

Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Dec 15, 2018

Download

Documents

leliem
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Programação paralela. Future e Stream

Docente: MSc. Angel Alberto Vazquez Sánchez

ISUTIC2017

Page 2: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Bibliografía

● I. Foster, Designing and Building Parallel Programs: Concepts and Tools for Parallel Software Engineering, 1st ed. Addison Wesley, 1995.

● Parallel Programming in Java, Coursera Course.

Page 3: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Introdução

● En ciencias de la computación, la programación funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa, que enfatiza los cambios de estado mediante la mutación de variables.

● La programación funcional tiene sus raíces en el cálculo lambda, un sistema formal desarrollado en los años 1930 para investigar la definición de función, la aplicación de las funciones y la recursión.

Page 4: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Introdução

● En la práctica, la diferencia entre una función matemática y la noción de una "función" utilizada en la programación imperativa, es que las funciones imperativas pueden tener efectos secundarios, como cambiar el valor de cálculos realizados previamente.

● Por esta razón carecen de transparencia referencial, es decir, la misma expresión sintáctica puede resultar en valores diferentes en varios momentos de la ejecución del programa.

● Con código funcional, en contraste, el valor generado por una función depende exclusivamente de los argumentos alimentados a la función.

● Al eliminar los efectos secundarios se puede entender y predecir el comportamiento de un programa mucho más fácilmente. Ésta es una de las principales motivaciones para utilizar la programación funcional.

Page 5: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Programação Funcional

A=F (B)

C=G(A)

D=H (A)

FA=Future {F (B)}

FC=Future {G(FA . get ())}

DD=Future {H (FA . get ())}

Block/Wait hasta que el objeto está disponible

F(B)

G(A) H(A)

joinjoin

Grafo de computação

Page 6: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Exemplo

FSUM1 = FUTURE {lowers}

FSUM2 = FUTURE {uppers}

SUM = FSUM1.get() + FSUM2.get()

Page 7: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● Em um aplicativo de thread único quando você chama um método retorna somente quando os cálculos são feitos (IOUtils.toString () vem do Apache Commons IO):

Page 8: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

Além disso, para reduzir a latência, você pode querer fazer outro processamento independente, enquanto aguarda os resultados.

Nos velhos tempos, você iniciaria um novo tópico e, de alguma forma, aguardaria resultados (memória compartilhada, bloqueios, terrível espera () / notificar () par, etc.)

Page 9: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

Com Future <T> é muito mais agradável:

Page 10: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

É importante que você entenda os princípios. startDownloading() não bloqueia, aguardando o site externo.

Em vez disso, ele retorna imediatamente, retornando um objeto leve do Futuro <String>. Este objeto é uma promessa de que a String estará disponível no futuro.

Não sei quando, mas mantenha essa referência e, uma vez que estiver lá, você poderá recuperá-la usando Future.get ().

Em outras palavras, o futuro é um proxy ou um wrapper em torno de um objeto que ainda não existe.

Uma vez que a computação assíncrona é feita, você pode extraí-la.

Page 11: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● Future.get() é o método mais importante. Bloqueia e aguarda até que o resultado prometido esteja disponível (resolvido).

● Então, se realmente precisamos de String, basta chamar get() e aguarde.

● Existe uma versão sobrecarregada que aceita tempo limite para que você não espere para sempre se algo for selvagem.

● TimeoutException é lançado se aguardar por muito tempo.

Page 12: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● Em alguns casos de uso, você pode querer espiar no Futuro e continuar se o resultado ainda não estiver disponível. Isso é possível com isDone().

● Imagine uma situação em que seu usuário aguarda uma computação assíncrona e você gostaria que ele soubesse que ainda estamos aguardando e fazemos alguma computação enquanto isso:

Page 13: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● A última chamada para o contentsFuture.get() é garantida para retornar imediatamente e não bloquear porque Future.isDone() retornou true.

● Se você seguir o padrão acima, certifique-se de que você não está ocupado esperando, chamando isDone() milhões de tempo por segundo.

Page 14: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● Cancelar futuros é o último aspecto que ainda não cobrimos.

● Imagine que você começou algum trabalho assíncrono e você só pode aguardar por um determinado período de tempo.

● Se não estiver lá depois, digamos, 2 segundos, desistimos e propagamos um erro ou trabalhamos ao redor.

● No entanto, se você é um bom cidadão, você deve de alguma forma contar esse futuro objeto: eu não preciso mais de você, esqueça isso.

● Você economiza recursos de processamento ao não executar tarefas obsoletas.

Page 15: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● A sintaxe é simple:

contentsFuture.cancel(true);

Page 16: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Future em Java

● Cancelar vem em dois sabores. – Ao passar falso ao parâmetro MayInterruptIfRunning, nós apenas cancelamos tarefas que ainda não começaram, quando o Futuro representa resultados de computação que nem sequer começaram.

– Mas se nosso Callable.call() já estiver no meio, deixamos que ele termine.

– No entanto, se passarmos true, Future.cancel() será mais agressivo, tentando interromper a execução de tarefas também.

Page 17: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Conclusão parcial

● Então, agora entendemos o que

Future<T>

● é - um lugar-titular para algo, que você vai conseguir no futuro.

● É como uma chave para um carro que ainda não era fabricado. Mas como você realmente obtém uma instância de Future<T> en tu aplicación?

Page 18: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Conclusão parcial

● Duas fontes mais comuns são pools de threads e métodos assíncronos.

● Assim, nosso método startDownloading() pode ser reescrito para:

Page 19: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Conclusão parcial

● Muitas regras de sintaxe, mas a idéia básica é simples: envolva cálculos de longa duração em Callable<String> e submit() eles para um grupo de threads de 10 threads.

● O envio de devoluções é uma implementação do Future<String>, provavelmente de alguma forma vinculada à sua tarefa e ao pool de threads. Obviamente, sua tarefa não foi executada imediatamente.

Page 20: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Conclusão parcial

● Em vez disso, ele é colocado em uma fila que é mais tarde (talvez até muito mais tarde) pesquisado por thread de um pool.

● Agora, deve ficar claro o que esses dois sabores de cancel() significa - você sempre pode cancelar a tarefa que ainda reside nessa fila. Mas cancelar a tarefa já executada é um pouco mais complexo.

Page 21: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Conclusão parcial

● Outro lugar onde você pode conhecer Future é Spring e EJB.

● Por exemplo, no marco de trabalho Spring, você pode simplesmente anotar seu método com @Async

Page 22: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Marco de trabalho Fork Join

● Otra vía para utilizar Future en Java es a través del marco de trabajo Fork-Join heredando de la clase RecursiveTask.

Page 23: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Page 24: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Page 25: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Page 26: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Page 27: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Dividir e Conquistar

Page 28: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Future

Page 29: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

public class ArraySumTask extends RecursiveTask<Double> {double[] array;int hi;int lo;public ArraySumTask(double[] array, int lo, int hi) {

this.array = array;this.hi = hi;this.lo = lo;

}@Overrideprotected Double compute() {

if(lo > hi) {return 0.0;

} else if(lo == hi) {return array[lo];

}else {int mid = (hi+lo)/2;ArraySumTask l = new ArraySumTask(array,lo, mid);ArraySumTask r = new ArraySumTask(array, mid+1, hi);r.fork();return l.compute() + r.join();

}}

}

Future GET

Page 30: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Marco de trabalho Fork Join

● Existem duas operações-chave que podem ser realizadas em um objeto futuro, A:– Atribuição - A pode ser atribuída uma referência a

um objeto futuro retornado por uma tarefa do formulário, future { tarefa com valor de retorno }⟨ ⟩ (usando a notação de pseudocódigo).

● O conteúdo do futuro objeto é obrigado a ser uma atribuição única (semelhante a uma variável final em Java) e não pode ser modificado após a devolução da tarefa futura.

Page 31: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Marco de trabalho Fork Join

● Existem duas operações-chave que podem ser realizadas em um objeto futuro, A:– Bloqueando leitura - a operação, A.get (), aguarda

até que a tarefa associada ao futuro objeto A tenha completado e, em seguida, propague o valor de retorno da tarefa como o valor retornado por A.get().

● Qualquer declaração, S, executada após A.get() pode ter certeza de que a tarefa associada ao futuro objeto A deve ter concluído antes de S iniciar a execução.

Page 32: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Memorização

Y 1=G (X1)

Y 2=G (X 2)

Y 3=G(X1)

Insert (G , X 1 ,Y 1)

Lookup(G , X1)Lookup(G, X 1)

FY 1=Future {G (X 1)}

Insert (G , X 1 , FY 1)

Y 2=G (X 2)

Y 3=Lookup (G , X1) .Get ()

Page 33: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Java Streams

for (Student student : list) {System.out.println(student);

}

list.stream().forEach(student->{System.out.println(student);

});

Forma secuencial:

Con Streams:

Page 34: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Java Streams

List<Student> activos = new ArrayList<>();Integer sum = 0;for (Student student : list) {

if(student.isActive)activos.add(student);

}for (Student student : activos) {

sum+=student.getAge();}Double average = sum.doubleValue()/activos.size();

Double average = list.stream().filter(s->s.isActive).mapToDouble(s->s.age).average().getAsDouble();

Forma secuencial:

Con Streams:.parallel()

Page 35: Programação paralela. Future e Stream · funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa,

Conclusões