Facilitando a Programação concorrente com o Fork/Join

Post on 14-Feb-2017

470 views 0 download

Transcript of Facilitando a Programação concorrente com o Fork/Join

FACILITANDO A PROGRAMAÇÃO

CONCORRENTE COM O FORK/JOIN

Mário Amaral@mario_fts

Thursday, December 6, 12

QUE MÁRIO?

Thursday, December 6, 12

QUE MÁRIO?

•Desenvolvedor Java desde 2004

Thursday, December 6, 12

QUE MÁRIO?

•Desenvolvedor Java desde 2004

• Instrutor na Caelum

Thursday, December 6, 12

QUE MÁRIO?

•Desenvolvedor Java desde 2004

• Instrutor na Caelum

• Caelum-Stella

Thursday, December 6, 12

QUE MÁRIO?

•Desenvolvedor Java desde 2004

• Instrutor na Caelum

• Caelum-Stella

• Personagem de games desde 1981

Thursday, December 6, 12

VAMOS FALAR DE PARALELISMO

Thursday, December 6, 12

POR QUE PARALELIZAR

• Ganhar tempo

Thursday, December 6, 12

POR QUE PARALELIZAR

• Aproveitar recursos ociosos

Thursday, December 6, 12

O QUE PARALELIZAR?

Thursday, December 6, 12

O QUE PARALELIZAR?

• Tarefas Independentes com processamento pesado

Thursday, December 6, 12

O QUE PARALELIZAR?

• Tarefas Independentes com processamento pesado

• Processar mensagens de uma fila

Thursday, December 6, 12

O QUE PARALELIZAR?

• Tarefas Independentes com processamento pesado

• Processar mensagens de uma fila

• Conversão de dados

Thursday, December 6, 12

O QUE PARALELIZAR?

• Tarefas Independentes com processamento pesado

• Processar mensagens de uma fila

• Conversão de dados

• Aplicar filtros em imagens

Thursday, December 6, 12

O PROBLEMA

Thursday, December 6, 12

O PROBLEMA

• Conversão de dados

Thursday, December 6, 12

O PROBLEMA

• Conversão de dados

•Dados de vendas

Thursday, December 6, 12

O PROBLEMA

• Conversão de dados

•Dados de vendas

• CSV => JSON

Thursday, December 6, 12

OS DADOS

Thursday, December 6, 12

OS DADOS • 1;1;04122012;fichario preto;9;33.55

Thursday, December 6, 12

OS DADOS • 1;1;04122012;fichario preto;9;33.55

Thursday, December 6, 12

OS DADOS • 1;1;04122012;fichario preto;9;33.55

{ "number": 1, "terminal": 1, "description": "fichario preto", "price": 33.55, "date": "04122012"}

Thursday, December 6, 12

PASSO A PASSO

• Ler os dados do CSV e converter para objetos.

• Para cada objeto, converter em Json.

• Adicionar o Json em uma lista de String.

• Gravar o conteúdo da lista em um arquivo.

Thursday, December 6, 12

SINGLE THREAD

• Processar tudo sequencialmente em um loop

• Implementação mais simples

Thursday, December 6, 12

CÓDIGO....

public List<String> toJson(List<?> list) { List<String> lines = new ArrayList<>(); for (Object value : list) { lines.add(new JsonObject(value)

.toString()); } return lines; }

Thursday, December 6, 12

TESTANDO

• 1 milhão de registros

• Executar 10 vezes seguidas cada método.

•Desconsiderar o menor e o maior tempo.

•Obter o tempo médio.

Thursday, December 6, 12

TEMPO

Método Tempo Médio (ms)

Single 5562

Thursday, December 6, 12

MULTI THREAD

Thursday, December 6, 12

MULTI THREAD

• Cada conversão é independente da outra.

Thursday, December 6, 12

MULTI THREAD

• Cada conversão é independente da outra.

• Múltiplos processadores

Thursday, December 6, 12

MULTI THREAD

• Cada conversão é independente da outra.

• Múltiplos processadores

•Dividir e distribuir!

Thursday, December 6, 12

threads.add(createANewThread(sales, jsons, beginIndex,finalIndex));

Thursday, December 6, 12

threads.add(createANewThread(sales, jsons, beginIndex,finalIndex)); beginIndex = finalIndex; finalIndex = finalIndex + amount >= size ?

size: finalIndex + amount;

Thursday, December 6, 12

while (true) { threads.add(createANewThread(sales, jsons, beginIndex,finalIndex)); beginIndex = finalIndex; finalIndex = finalIndex + amount >= size ?

size: finalIndex + amount;

}

Thursday, December 6, 12

while (true) { threads.add(createANewThread(sales, jsons, beginIndex,finalIndex)); beginIndex = finalIndex; finalIndex = finalIndex + amount >= size ?

size: finalIndex + amount;

if (beginIndex == size) { break; }}

Thursday, December 6, 12

protected List<String> convertToJson(List<Sale> sales){...

while (true) { threads.add(createANewThread(sales, jsons, beginIndex,finalIndex)); beginIndex = finalIndex; finalIndex = finalIndex + amount >= size ?

size: finalIndex + amount;

if (beginIndex == size) { break; }}

}

Thursday, December 6, 12

protected List<String> convertToJson(List<Sale> sales){

int size = sales.size(); int amount = size / NUMBER_OF_THREADS; //4 int beginIndex = 0; int finalIndex = amount;

List<Thread> threads = new ArrayList<>(); List<String> jsons = Collections.synchronizedList(

new ArrayList<String>());

while (true) { //Cria uma nova thread para cada parte

}

Thursday, December 6, 12

protected List<String> convertToJson(List<Sale> sales){

... for (Thread thread : threads) { thread.start(); }

return jsons;

}

Thursday, December 6, 12

protected List<String> convertToJson(List<Sale> sales){

... for (Thread thread : threads) { thread.start(); }

for (Thread thread : threads) { thread.join(); }

return jsons;

}

Thursday, December 6, 12

@Override protected List<String> convertToJson(List<Sale> vendas) throws Exception {

System.out.println("Convert to json....");

int size = vendas.size(); int amount = size / NUMBER_OF_THREADS; //4 int beginIndex = 0; int finalIndex = amount;

List<Thread> threads = new ArrayList<>(); List<String> jsons = Collections.synchronizedList(new ArrayList<String>());

while (true) { threads.add(createANewThread(vendas, jsons, beginIndex, finalIndex)); beginIndex = finalIndex; finalIndex = finalIndex + amount >= size ? size: finalIndex + amount;

if (beginIndex == size) { break; } }

for (Thread thread : threads) { thread.start(); }

for (Thread thread : threads) { thread.join(); }

System.out.println("Finished!\n"); return jsons;

}Thursday, December 6, 12

TEMPO

Método Tempo Médio (ms)

Single 5562

Multi Thread 3739

Thursday, December 6, 12

COMPARATIVO

0

2000

4000

6000

Tempo

37395562

Single Multi Thread

Thursday, December 6, 12

DIFICULDADES

Thursday, December 6, 12

DIFICULDADES

•Decidir a quantidade de Threads

Thursday, December 6, 12

DIFICULDADES

•Decidir a quantidade de Threads

•Dividir o trabalho

Thursday, December 6, 12

DIFICULDADES

•Decidir a quantidade de Threads

•Dividir o trabalho

• Juntar tudo no final

Thursday, December 6, 12

protected List<String> convertToJson(List<Sale> sales){

int size = sales.size(); int amount = size / NUMBER_OF_THREADS; //4 int beginIndex = 0; int finalIndex = amount;

List<Thread> threads = new ArrayList<>(); List<String> jsons = Collections.synchronizedList(

new ArrayList<String>());

while (true) { //Cria uma nova thread para cada parte

}

Thursday, December 6, 12

FORK / JOIN

Thursday, December 6, 12

FORK / JOIN

• Java 7

Thursday, December 6, 12

FORK / JOIN

• Java 7

•Dividir tarefas entre múltiplos processadores

Thursday, December 6, 12

FORK / JOIN

• Java 7

•Dividir tarefas entre múltiplos processadores

• Tarefas que podem ser quebradas recursivamente

Thursday, December 6, 12

class ExemploForkJoin extends RecursiveTask<Long>{

@Override protected Long compute() {

if(qtdeDeDados < LIMITE){ // execute a tarefa }else{ //Divida o trabalho entre subtarefas //Execute as subtarefas e espere o resultado } }}

COMO FUNCIONA

Thursday, December 6, 12

COMO FUNCIONA

Thursday, December 6, 12

COMO FUNCIONA

Thursday, December 6, 12

COMO FUNCIONA

Thursday, December 6, 12

COMO FUNCIONA

Thursday, December 6, 12

COMO FUNCIONA

fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

join()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

join() join()

Thursday, December 6, 12

COMO FUNCIONA

fork() fork()

join() join()

Thursday, December 6, 12

COMO FUNCIONA

fork()

join()

fork()

join() join()

Thursday, December 6, 12

COMO FUNCIONA

fork()

join()

fork()

join()

join() join()

Thursday, December 6, 12

IMPLEMENTANDOpublic class JsonTask extends RecursiveTask<List<String>>{

private final int THRESHOLD = 10000; private List<Sale> list; //constructor...

@Override protected List<String> compute() { }}

Thursday, December 6, 12

IMPLEMENTANDOpublic class JsonTask extends RecursiveTask<List<String>>{

private final int THRESHOLD = 10000; private List<Sale> list; //constructor...

@Override protected List<String> compute() { }}

Thursday, December 6, 12

IMPLEMENTANDOpublic class JsonTask extends RecursiveTask<List<String>>{

private final int THRESHOLD = 10000; private List<Sale> list; //constructor...

@Override protected List<String> compute() { }}

Thursday, December 6, 12

IMPLEMENTANDOpublic class JsonTask extends RecursiveTask<List<String>>{

private final int THRESHOLD = 10000; private List<Sale> list; //constructor...

@Override protected List<String> compute() { }}

Thursday, December 6, 12

@Overrideprotected List<String> compute() { List<String> jsons = new ArrayList<>(); int size = list.size(); if ( size < THRESHOLD){ jsons.addAll(new JsonMapper().toJson(list)); }else{ ... } return jsons;}

Thursday, December 6, 12

}else{

}

Thursday, December 6, 12

}else{ JsonTask left = new JsonTask(list.subList(0, size / 2));

}

Thursday, December 6, 12

}else{ JsonTask left = new JsonTask(list.subList(0, size / 2)); JsonTask right = new JsonTask(list.subList(size / 2, size));

}

Thursday, December 6, 12

}else{ JsonTask left = new JsonTask(list.subList(0, size / 2)); JsonTask right = new JsonTask(list.subList(size / 2, size)); left.fork();

}

Thursday, December 6, 12

}else{ JsonTask left = new JsonTask(list.subList(0, size / 2)); JsonTask right = new JsonTask(list.subList(size / 2, size)); left.fork(); right.fork();

}

Thursday, December 6, 12

}else{ JsonTask left = new JsonTask(list.subList(0, size / 2)); JsonTask right = new JsonTask(list.subList(size / 2, size)); left.fork(); right.fork();

jsons.addAll(right.join()); jsons.addAll(left.join());}

Thursday, December 6, 12

P

Thursday, December 6, 12

P

L

fork()

R

fork()

Thursday, December 6, 12

P

L

fork()

join()

R

fork()

join()

Thursday, December 6, 12

}else{ JsonTask left = new JsonTask(list.subList(0, size / 2)); JsonTask right = new JsonTask(list.subList(size / 2, size)); left.fork(); right.fork();

jsons.addAll(right.join()); jsons.addAll(left.join());}

Thursday, December 6, 12

P

Poolde Threads

Thursday, December 6, 12

P

Poolde Threads P

Thursday, December 6, 12

P

L

fork()

R

fork()

Poolde Threads P

Thursday, December 6, 12

P

L

fork()

R

fork()

Poolde Threads P L R

Thursday, December 6, 12

}else{ JsonTask jsonTaskLeft = new JsonTask(list.subList(0, size / 2)); JsonTask jsonTaskRight = new JsonTask(list.subList(size / 2, size)); jsonTaskLeft.fork(); jsonTaskRight.fork();

jsons.addAll(jsonTaskRight.join()); jsons.addAll(jsonTaskLeft.join());}

Thursday, December 6, 12

P

L

fork()

R

fork()

Poolde Threads P L R

Thursday, December 6, 12

RECURSO OCIOSO

Thursday, December 6, 12

}else{ JsonTask jsonTaskLeft = new JsonTask(list.subList(0, size / 2)); JsonTask jsonTaskRight = new JsonTask(list.subList(size / 2, size)); jsonTaskLeft.fork(); jsonTaskRight.fork();

jsons.addAll(jsonTaskRight.join()); jsons.addAll(jsonTaskLeft.join());}

Thursday, December 6, 12

}else{ JsonTask jsonTaskLeft = new JsonTask(list.subList(0, size / 2)); JsonTask jsonTaskRight = new JsonTask(list.subList(size / 2, size)); jsonTaskLeft.fork(); jsonTaskRight.fork();

jsons.addAll(jsonTaskRight.join()); jsons.addAll(jsonTaskLeft.join());}

Thursday, December 6, 12

}else{ JsonTask jsonTaskLeft = new JsonTask(list.subList(0, size / 2)); JsonTask jsonTaskRight = new JsonTask(list.subList(size / 2, size)); jsonTaskLeft.fork();

jsons.addAll(jsonTaskRight.join()); jsons.addAll(jsonTaskLeft.join());}

Thursday, December 6, 12

}else{ JsonTask jsonTaskLeft = new JsonTask(list.subList(0, size / 2)); JsonTask jsonTaskRight = new JsonTask(list.subList(size / 2, size)); jsonTaskLeft.fork();

jsons.addAll(jsonTaskRight.compute()); jsons.addAll(jsonTaskLeft.join());}

Thursday, December 6, 12

P

Poolde Threads

L R

P

Thursday, December 6, 12

P

L R

Poolde Threads

LL

P

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

LL

P

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

L

P

L

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

L

P L

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

R

LP

Thursday, December 6, 12

P

L

fork()

R

compute()

Poolde Threads

R

LP

Thursday, December 6, 12

P

L

fork()

R

compute()

Poolde Threads R L

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

compute()

LR

P

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

compute()

return

LR

P

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads

compute()

return

LP

Thursday, December 6, 12

}else{ JsonTask jsonTaskLeft = new JsonTask(list.subList(0, size / 2)); JsonTask jsonTaskRight = new JsonTask(list.subList(size / 2, size)); jsonTaskLeft.fork();

jsons.addAll(jsonTaskRight.compute()); jsons.addAll(jsonTaskLeft.join());}

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads P L

compute()

return

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads P L

compute()

returnjoin()

Thursday, December 6, 12

P

L

fork()

R

Poolde Threads P

compute()

returnjoin()

Thursday, December 6, 12

EXECUTANDO public class JsonForkJoinConverter {protected List<String> convertToJson(List<Sale> sales){

ForkJoinPool forkJoinPool = new ForkJoinPool(); return forkJoinPool.invoke(new JsonTask(sales)); }}

Thursday, December 6, 12

TEMPO

MétodoTempo

Médio (ms)

Single 5562

Multi Thread 3739

Fork/Join 3461

Thursday, December 6, 12

COMPARATIVO

0

2000

4000

6000

Tempo

346137395562

Single Multi Thread Fork/join

Thursday, December 6, 12

@Override protected List<String> compute() { List<String> jsons = new ArrayList<>(); int size = list.size(); if ( size < THRESHOLD){ jsons.addAll(new JsonMapper().toJson(list)); } else{ JsonTask jsonTaskFirst = new JsonTask(list.subList(0, size / 2)); jsonTaskFirst.fork(); JsonTask jsonTaskSecond = new JsonTask(list.subList(size / 2, size)); jsons.addAll(jsonTaskSecond.compute()); jsons.addAll(jsonTaskFirst.join()); } return jsons; }

Thursday, December 6, 12

PROBLEMS?

Thursday, December 6, 12

PROBLEMS?

Thursday, December 6, 12

A ORDEM DAS CHAMADAS

•Ordem das chamadas é importante.

• Perde todo o paralelismo

Thursday, December 6, 12

left.fork();long rightAns = right.compute();long leftAns = left.join();return leftAns + rightAns;

P

P

L R

Thursday, December 6, 12

left.fork();long rightAns = right.compute();long leftAns = left.join();return leftAns + rightAns;

P

P

L R

fork()

L

Thursday, December 6, 12

left.fork();long rightAns = right.compute();long leftAns = left.join();return leftAns + rightAns;

P

R

L R

fork()

L

compute()

Thursday, December 6, 12

left.fork();long rightAns = right.compute();long leftAns = left.join();return leftAns + rightAns;

P

P

L R

fork()

L

compute()

return

Thursday, December 6, 12

left.fork();long rightAns = right.compute();long leftAns = left.join();return leftAns + rightAns;

P

P

L R

fork() compute()

returnjoin()

Thursday, December 6, 12

left.fork();

return leftAns + rightAns;

long rightAns = right.compute();long leftAns = left.join();

Thursday, December 6, 12

left.fork();

return leftAns + rightAns;long rightAns = right.compute();long leftAns = left.join();

Thursday, December 6, 12

P

P

L R

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

Thursday, December 6, 12

P

P

L R

fork()

L

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

Thursday, December 6, 12

P

P

L R

fork()

L

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

Bloqueia a thread!

Thursday, December 6, 12

P

P

L R

fork()

L

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

join()

Thursday, December 6, 12

P

R

L R

fork()

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

join()

compute()

Thursday, December 6, 12

P

R

L R

fork() compute()

return

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

join()

Thursday, December 6, 12

P

P

L R

fork() compute()

returnjoin()

left.fork();long leftAns = left.join();long rightAns = right.compute();return leftAns + rightAns;

Thursday, December 6, 12

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

Thursday, December 6, 12

P

P

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

Thursday, December 6, 12

P

P

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

compute()

Thursday, December 6, 12

P

R

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

compute()

Thursday, December 6, 12

P

R

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

compute()

return

Thursday, December 6, 12

P

P

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

compute()

return

Thursday, December 6, 12

P

P

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

compute()

return

fork()

L

Thursday, December 6, 12

P

P

L R

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

compute()

return

fork()

L

Thursday, December 6, 12

P

P

L R

fork() compute()

returnjoin()

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

Thursday, December 6, 12

P

P

L R

fork() compute()

returnjoin()

long rightAns = right.compute();left.fork();long leftAns = left.join();return leftAns + rightAns;

Executa Sequencialmente

Thursday, December 6, 12

left.fork();long rightAns = right.compute();long leftAns = left.join();return leftAns + rightAns;

Thursday, December 6, 12

OBRIGADO!

github.com/mariofts

@mario_fts

mario.amaral@caelum.com.br

Thursday, December 6, 12