Facilitando a Programação concorrente com o Fork/Join
-
Upload
mario-amaral -
Category
Technology
-
view
470 -
download
0
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
• Código aqui:
• github.com/mariofts/javaOneBR-2012
• Links / Refs:
• http://homes.cs.washington.edu/~djg/teachingMaterials/grossmanSPAC_forkJoinFramework.html
• http://www.oracle.com/technetwork/articles/java/fork-join-422606.html
• http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
Thursday, December 6, 12
OBRIGADO!
github.com/mariofts
@mario_fts
Thursday, December 6, 12