Базові принципи багатопотоковості

Оптимізація коду в Java

Pavlos Kosmetatos

Lead Engineer @Wealthyhood

Послідовне vs паралельне виконання

  • Послідовне виконання -> операції йдуть одна за одною
  • Паралельне виконання -> кілька операцій тривають одночасно

Як?

  • Сучасні CPU мають кілька ядер
  • Потік: найменша одиниця виконання програми
  • Багатопотоковість розподіляє роботу між ядрами

Однопотоковість — це мов одна смуга руху: авто їдуть одне за одним. Багатопотоковість — кілька смуг, де авто рухаються паралельно!

Оптимізація коду в Java

Використання потоків

  • Клас Thread дає змогу створювати нові шляхи виконання
  • Кожен Thread може виконуватися незалежно
Runnable task = () -> {
    System.out.println("Processing on thread: " + 
                       Thread.currentThread().getName());
};

Thread thread = new Thread(task);
thread.start();
Processing on thread: Thread-0
Оптимізація коду в Java

Робота з кількома потоками

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
Оптимізація коду в Java

Паралельні стріми

  • Streams — можливість Java 8+ для спрощеного паралелізму
  • Автоматично керують створенням і життєвим циклом потоків
  • Два способи створення:
    • collection.parallelStream()
    • Stream.of(...).parallel()
Оптимізація коду в Java

Приклад паралельних стрімів

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

// Sequential processing with stream List<Integer> result2 = numbers.stream() .map(n -> n * 2) .collect(Collectors.toList());
// Parallel processing with parallel stream List<Integer> result3 = numbers.parallelStream() .map(n -> n * 2) .collect(Collectors.toList());
Оптимізація коду в Java

Коли варто використовувати паралельність

  • Обчислювально інтенсивні операції
  • Незалежна обробка даних
  • Великі колекції даних
  • Доступно ядер CPU > 1
  • Накладні витрати паралелізації можуть бути зайвими для:
    • Малих наборів даних
    • Простих операцій
Оптимізація коду в Java

Підсумок

  • Клас Thread для створення паралельних шляхів виконання
  • Паралельні стріми для спрощеної обробки колекцій
  • Переваги залежать від:
    • Типу навантаження
    • Розміру даних
    • Кількості доступних ядер
Оптимізація коду в Java

Давайте потренуємось!

Оптимізація коду в Java

Preparing Video For Download...