Princípios básicos de multi-threading

Otimização de Código em Java

Pavlos Kosmetatos

Lead Engineer @Wealthyhood

Execução sequencial vs. paralela

  • Processamento sequencial -> operações ocorrem uma após a outra
  • Processamento paralelo -> várias operações ocorrem ao mesmo tempo

Como?

  • CPUs modernas têm vários núcleos
  • Thread: a menor unidade de execução de um programa
  • Multi-threading distribui o trabalho entre esses núcleos

Single-threading é como uma pista única onde os carros vão em fila. Multi-threading é como várias pistas com carros andando ao mesmo tempo!

Otimização de Código em Java

Usando threads

  • A classe Thread permite criar novos fluxos de execução
  • Cada Thread pode executar de forma independente
Runnable task = () -> {
    System.out.println("Processing on thread: " + 
                       Thread.currentThread().getName());
};

Thread thread = new Thread(task);
thread.start();
Processing on thread: Thread-0
Otimização de Código em Java

Trabalhando com múltiplas threads

List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 4; i++) {
    Thread thread = new Thread(() -> System.out.println("Processing data on Thread-" + i));
    threads.add(thread);
    thread.start();
}

for (Thread t : threads) {
    t.join(); // Waits for all threads to complete
}
// Processing data on Thread-0
// Processing data on Thread-2
// Processing data on Thread-1
// Processing data on Thread-3
Otimização de Código em Java

Streams paralelos

  • Streams - recurso do Java 8+ para paralelismo simplificado
  • Lida automaticamente com criação e gestão de threads
  • Duas formas de criar:
    • collection.parallelStream()
    • Stream.of(...).parallel()
Otimização de Código em Java

Exemplo de streams paralelos

// Processamento sequencial
List<Integer> result1 = new ArrayList<>();
for (int i = 0; i < numbers.size(); i++) {
    result1.add(numbers.get(i) * 2);
}

// Processamento sequencial com stream List<Integer> result2 = numbers.stream() .map(n -> n * 2) .collect(Collectors.toList());
// Processamento paralelo com parallel stream List<Integer> result3 = numbers.parallelStream() .map(n -> n * 2) .collect(Collectors.toList());
Otimização de Código em Java

Quando usar processamento paralelo

  • Operações intensivas de CPU
  • Processamento de dados independentes
  • Coleções de dados grandes
  • Núcleos de CPU disponíveis > 1
  • A sobrecarga da paralelização pode não valer a pena para:
    • Conjuntos de dados pequenos
    • Operações simples
Otimização de Código em Java

Resumo

  • Classe Thread para criar caminhos de execução paralelos
  • Streams paralelos para simplificar o processamento de coleções
  • Os benefícios dependem de:
    • Tipo de carga de trabalho
    • Tamanho dos dados
    • Núcleos disponíveis
Otimização de Código em Java

Vamos praticar!

Otimização de Código em Java

Preparing Video For Download...