Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ ForkJoinPool — это специальная реализация пула потоков, предназначенная для выполнения параллельных задач с использованием алгоритма разделяй и властвуй (divide and conquer). Этот пул потоков был представлен в Java 7 как часть библиотеки java.util.concurrent.

Использует подход "разделяй и властвуй", где задача разбивается на подзадачи до тех пор, пока они не станут достаточно маленькими для последовательного решения. Для этого используются классы RecursiveTask<V> (возвращает результат) и RecursiveAction (без результата).

ForkJoinPool динамически управляет количеством потоков, при необходимости создавая новые. Обычно это количество соответствует числу процессоров, доступных в системе.

Использует технику work-stealing, где потоки, завершившие свои задачи, могут "красть" задачи у других потоков, чтобы эффективно использовать ресурсы процессора.

ForkJoinPool обладает высокой производительностью для задач, которые можно разбить на независимые подзадачи.

Основные методы:

invoke(): синхронно запускает задачу и ждет её завершения.

submit(): запускает задачу асинхронно.

execute(): также запускает задачу асинхронно, но не возвращает результат.

Пример использования:

import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;

class SumTask extends RecursiveTask<Integer> {
private final int[] array;
private final int start, end;
private final int threshold = 10;

public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}

@Override
protected Integer compute() {
if (end - start <= threshold) {
// Базовый случай: небольшая задача
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// Разделяем задачу
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(array, start, mid);
SumTask rightTask = new SumTask(array, mid, end);

leftTask.fork(); // Асинхронно запускаем левую подзадачу
int rightResult = rightTask.compute(); // Синхронно вычисляем правую подзадачу
int leftResult = leftTask.join(); // Ждем завершения левой подзадачи

return leftResult + rightResult;
}
}
}

public class ForkJoinExample {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
SumTask task = new SumTask(array, 0, array.length);
int result = pool.invoke(task);
System.out.println("Сумма: " + result);
}
}

Этот код создает задачу для суммирования массива, разбивая его на подзадачи.

#java #ForkJoinPool
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141🔥1
⚡️ Разница между ExecutorService и ForkJoinPool

Оба механизма предназначены для работы с многопоточностью, но у них разные задачи:

ExecutorService – управляет пулом потоков, подходит для выполнения Runnable и Callable.
ForkJoinPool – оптимизирован для рекурсивных задач, использует алгоритм work-stealing.

✔️ Пример ExecutorService:


ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(() -> System.out.println("Task executed"));
executor.shutdown();


✔️ Пример ForkJoinPool:


import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;

class SumTask extends RecursiveTask<Integer> {
private final int[] array;
private final int start, end;
private final int threshold = 10;

public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}

@Override
protected Integer compute() {
if (end - start <= threshold) {
// Базовый случай: небольшая задача
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// Разделяем задачу
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(array, start, mid);
SumTask rightTask = new SumTask(array, mid, end);

leftTask.fork(); // Асинхронно запускаем левую подзадачу
int rightResult = rightTask.compute(); // Синхронно вычисляем правую подзадачу
int leftResult = leftTask.join(); // Ждем завершения левой подзадачи

return leftResult + rightResult;
}
}
}

public class ForkJoinExample {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
SumTask task = new SumTask(array, 0, array.length);
int result = pool.invoke(task);
System.out.println("Сумма: " + result);
}
}


ForkJoinPool динамически управляет количеством потоков, при необходимости создавая новые. Обычно это количество соответствует числу процессоров, доступных в системе.

💡 Совет: Используйте ForkJoinPool для рекурсивных задач, а ExecutorService – для классической многопоточности.

#java #executorservice #forkjoinpool #multithreading
Please open Telegram to view this post
VIEW IN TELEGRAM
👍104🔥1👏1