💡 Как управлять потоками с помощью ExecutorCompletionService
ExecutorCompletionService — это инструмент для удобной работы с потоками, позволяющий эффективно управлять задачами, выполняющимися асинхронно, и получать результаты по мере их готовности. Он сочетает в себе возможности
📌 Преимущества ExecutorCompletionService:
1️⃣ Удобное управление задачами: позволяет управлять и отслеживать несколько асинхронных задач одновременно.
2️⃣ Получение результатов по мере выполнения: результаты задач можно получать в том порядке, в котором они завершены.
3️⃣ Обработка ошибок: позволяет перехватывать исключения, возникающие в процессе выполнения задач.
📌 Пример использования ExecutorCompletionService:
📌 Как это работает:
1️⃣ Создаём
2️⃣ Задачи отправляются в очередь с помощью метода
3️⃣ Метод
4️⃣ Метод
📌 Когда использовать ExecutorCompletionService?
- Когда необходимо параллельно выполнить несколько задач и получить результаты по мере их завершения.
- В ситуациях, когда задачи могут занять разное время на выполнение.
- Для эффективного управления потоками в многозадачных приложениях.
💡 Совет: Используйте
#Java #ExecutorCompletionService #ПараллельноеВыполнение #Многозадачность
ExecutorCompletionService — это инструмент для удобной работы с потоками, позволяющий эффективно управлять задачами, выполняющимися асинхронно, и получать результаты по мере их готовности. Он сочетает в себе возможности
ExecutorService и очередь для получения результатов выполнения задач. 📌 Преимущества ExecutorCompletionService:
1️⃣ Удобное управление задачами: позволяет управлять и отслеживать несколько асинхронных задач одновременно.
2️⃣ Получение результатов по мере выполнения: результаты задач можно получать в том порядке, в котором они завершены.
3️⃣ Обработка ошибок: позволяет перехватывать исключения, возникающие в процессе выполнения задач.
📌 Пример использования ExecutorCompletionService:
import java.util.concurrent.*;
public class ExecutorCompletionServiceExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(3);
ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(executor);
// Добавляем задачи в очередь
for (int i = 0; i < 5; i++) {
final int taskId = i;
completionService.submit(() -> {
// Задача выполняется
Thread.sleep(1000); // Эмулируем работу
return taskId * 2;
});
}
// Получаем результаты по мере их готовности
for (int i = 0; i < 5; i++) {
Future<Integer> result = completionService.take(); // Возвращает первый завершившийся результат
System.out.println("Задача завершена с результатом: " + result.get());
}
executor.shutdown();
}
}
📌 Как это работает:
1️⃣ Создаём
ExecutorCompletionService, передавая ему пул потоков. 2️⃣ Задачи отправляются в очередь с помощью метода
submit(). 3️⃣ Метод
take() извлекает завершённую задачу и её результат. 4️⃣ Метод
get() позволяет получить результат выполнения задачи. 📌 Когда использовать ExecutorCompletionService?
- Когда необходимо параллельно выполнить несколько задач и получить результаты по мере их завершения.
- В ситуациях, когда задачи могут занять разное время на выполнение.
- Для эффективного управления потоками в многозадачных приложениях.
💡 Совет: Используйте
ExecutorCompletionService для повышения производительности, когда важно обрабатывать результаты задач в порядке их завершения. #Java #ExecutorCompletionService #ПараллельноеВыполнение #Многозадачность
👍15❤3
CompletableFuture в Java?CompletableFuture — это улучшенная альтернатива Future, появившаяся в Java 8, позволяющая работать с асинхронными вычислениями.1️⃣ Позволяет запускать задачи в фоне и получать результат позже.
2️⃣ Поддерживает цепочки операций
.thenApply(), .thenAccept().3️⃣ Может выполняться параллельно без блокировки основного потока.
import java.util.concurrent.CompletableFuture;
public class AsyncExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> "Hello, Async!")
.thenAccept(System.out::println);
}
}
CompletableFuture, если хотите писать неблокирующий и эффективный код.#java #completablefuture #async
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤2
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
👍10❤4🔥1👏1
TreeSet и HashSetОба класса реализуют
Set, но у них разные свойства:• HashSet – хранит элементы в случайном порядке, обеспечивает быстрые операции add() и remove().• TreeSet – хранит элементы в отсортированном порядке, но работает медленнее.Set<Integer> hashSet = new HashSet<>(Set.of(3, 1, 2)); // [3, 1, 2] (порядок может быть разным)
Set<Integer> treeSet = new TreeSet<>(Set.of(3, 1, 2)); // [1, 2, 3] (отсортировано)
HashSet для быстрого доступа и TreeSet, если важен порядок элементов.#java #treeset #hashset #collections
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤2🔥1
deep copy и shallow copyПри копировании объектов в Java различают два типа копий:
• Shallow copy – копирует только ссылки на вложенные объекты, изменения в одном объекте затронут копию.• Deep copy – создаёт полную копию, включая все вложенные объекты.
class Person implements Cloneable {
String name;
Person(String name) {
this.name = name;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Для создания полной копии можно использовать конструктор копирования или сериализацию/десериализацию.
import java.io.*;
public class DeepCopyExample {
public static void main(String[] args) {
Person person = new Person("John", 30);
Person deepCopy = deepCopy(person);
System.out.println("Original: " + person.getName() + ", " + person.getAge());
System.out.println("Deep copy: " + deepCopy.getName() + ", " + deepCopy.getAge());
}
public static <T extends Serializable> T deepCopy(T object) {
try {
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);
objectOutputStream.writeObject(object);
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
T copy = (T) objectInputStream.readObject();
return copy;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
deep copy, если объект содержит изменяемые вложенные объекты, иначе изменения в одном месте могут неожиданно повлиять на копию.#java #deepcopy #shallowcopy #clone
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤1
try-with-resources?Конструкция
try-with-resources, появившаяся в Java 7, позволяет автоматически закрывать ресурсы (например, файлы, потоки).1️⃣ Облегчает управление ресурсами.
2️⃣ Избегает утечек памяти.
Пример:
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}try-with-resources, должны реализовывать интерфейс AutoCloseable.#java #trywithresources #java7
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤1🔥1
Работа с большими
List и Map в Java может привести к высоким затратам памяти и снижению производительности. Как этого избежать?ArrayList без задания начального размераList<String> list = new ArrayList<>(); // По умолчанию – 10 элементов
for (int i = 0; i < 1000000; i++) {
list.add("data");
}
List<String> list = new ArrayList<>(1000000);
HashMap без настройки initialCapacity и loadFactorПо умолчанию
HashMap перераспределяет бакеты при загрузке 75%, что может вызвать лишние перераспределения.Map<String, String> map = new HashMap<>(1000000, 0.9f);
LinkedList вместо ArrayList для поискаList<String> list = new LinkedList<>();
list.get(5000); // O(n)
ArrayList, если часто выполняете get()-XX:+PrintGCDetails и jcmd GC.heap_info, чтобы следить за лишними выделениями памяти.#java #collections #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥5❤2
Stream API, которые упростят кодStream API – мощный инструмент, но в нём есть интересные методы, о которых многие забывают.takeWhile() – берёт элементы, пока условие true.dropWhile() – пропускает элементы, пока условие true.iterate() – создаёт бесконечный поток.flatMap() – преобразует вложенные структуры в плоский поток.collect(Collectors.toMap()) – собирает Stream в Map.
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
numbers.stream()
.takeWhile(n -> n < 4)
.forEach(System.out::println); // 1, 2, 3
for.#java #streamapi #functionalprogramming
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26❤3🔥1
switch с выражениями в Java 12+?В Java 12 появился улучшенный
switch, который позволяет возвращать значения и использовать case без break.• Код стал короче и читабельнее.• Можно присваивать результат switch переменной.• Поддерживает yield для возврата значений.
String result = switch (day) {
case "Monday", "Tuesday" -> "Рабочий день";
case "Saturday", "Sunday" -> "Выходной";
default -> "Неизвестный день";
};
System.out.println(result);
switch для улучшения читаемости кода и уменьшения дублирования break.#java #switch #java12
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥3❤2
List, Set и MapЭти три интерфейса из
java.util используются для хранения коллекций данных, но имеют разные свойства:•
List – упорядоченная коллекция, допускает дубликаты (ArrayList, LinkedList).•
Set – уникальные элементы, порядок может быть произвольным (HashSet, TreeSet).•
Map – хранит пары "ключ-значение" (HashMap, TreeMap).
List<String> list = new ArrayList<>(List.of("A", "B", "A")); // [A, B, A]
Set<String> set = new HashSet<>(Set.of("A", "B", "A")); // [A, B]
Map<Integer, String> map = new HashMap<>(Map.of(1, "One", 2, "Two")); // {1=One, 2=Two}
List, если важен порядок и дубликаты, Set – если важна уникальность, Map – для работы с парами ключ-значение.#java #collections #list #set #map
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2
Text Blocks (
""") позволяют удобно работать с многострочными строками без необходимости экранировать кавычки.• Улучшают читаемость кода.• Поддерживают форматирование и перенос строк.• Упрощают работу с JSON, SQL и HTML.
String json = """
{
"name": "Alice",
"age": 30
}
""";
System.out.println(json);
#java #textblocks #java15
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥2❤1💯1
<?>В Java
<?> называется неограниченным wildcard. Он обозначает, что параметр типа может быть любым, то есть неизвестным на этапе компиляции. Это удобно, когда метод или класс работают с обобщёнными типами, но конкретный тип элемента не важен.Например, выражение
List<?> означает список, элементы которого могут быть любого типа. Такой подход позволяет писать более универсальный и гибкий код, но при этом накладывает ограничения: мы не можем добавлять новые элементы в коллекцию, поскольку компилятор не знает конкретный тип элементов, чтобы обеспечить безопасность типов.
import java.util.List;
public class WildcardExample {
public static void printList(List<?> list) {
for (Object element : list) { // Элементы можно читать как Object
System.out.println(element);
}
}
public static void main(String[] args) {
List<Integer> intList = List.of(1, 2, 3);
List<String> strList = List.of("A", "B", "C");
printList(intList); // Вывод: 1 2 3
printList(strList); // Вывод: A B C
}
}
Здесь
List<?> позволяет передавать любой тип списка, но мы можем безопасно читать только как Object.
public static void addElement(List<?> list) {
// list.add("Hello"); // Ошибка компиляции!
}
#java #wildcard
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18❤1🔥1
extends (ограничение сверху)Если мы хотим работать только с числами (
Number и его потомками), можно использовать ? extends Number:
import java.util.List;
public class WildcardExample {
public static double sumNumbers(List<? extends Number> list) {
double sum = 0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
public static void main(String[] args) {
List<Integer> intList = List.of(1, 2, 3);
List<Double> doubleList = List.of(1.1, 2.2, 3.3);
System.out.println(sumNumbers(intList)); // Вывод: 6.0
System.out.println(sumNumbers(doubleList)); // Вывод: 6.6
}
}
🔹
? extends Number означает, что list может быть списком любого подкласса Number (Integer, Double, Float и т. д.).🔹 Это позволяет безопасно читать значения, но не добавлять новые (аналогично
<?>).#java #wildcard
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤1
super (ограничение снизу)Иногда нужно работать с базовыми типами (например, добавлять в
List<? super Integer> только Integer и его предков):
import java.util.List;
import java.util.ArrayList;
public class WildcardExample {
public static void addNumbers(List<? super Integer> list) {
list.add(10);
list.add(20);
}
public static void main(String[] args) {
List<Number> numberList = new ArrayList<>();
addNumbers(numberList);
System.out.println(numberList); // Вывод: [10, 20]
}
}
🔹
? super Integer означает, что list может быть списком Integer или его родительских классов (Number, Object).🔹 Это позволяет безопасно добавлять
Integer, но при чтении придется использовать Object.#java #wildcard
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤1
java.util.Formatter позволяет создавать отформатированные строки по аналогии с printf() в C.Formatter может форматировать числа, дату, время, выравнивать текст, управлять пробелами и отступами, а так же работать с локалями.
import java.util.Formatter;
public class FormatterExample {
public static void main(String[] args) {
try (Formatter formatter = new Formatter()) {
formatter.format("Привет, %s! Тебе %d лет.", "Андрей", 25);
System.out.println(formatter);
// Привет, Андрей! Тебе 25 лет.
}
}
}
Можно не просто форматировать строки, но и записывать их в файл:
import java.io.FileNotFoundException;
import java.util.Formatter;
public class FileWriteExample {
public static void main(String[] args) throws FileNotFoundException {
try (Formatter formatter = new Formatter("output.txt")) {
formatter.format("Имя: %s, Возраст: %d%n", "Алиса", 30);
}
}
}
Теперь в файле
output.txt будет строка:Имя: Алиса, Возраст: 30#java #Formatter
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍3❤2👏2
ThreadLocal может привести к утечкам памяти?ThreadLocal – удобный способ хранения данных в потоке, но может привести к утечкам памяти.• Потоки из ThreadPool не удаляются сразу после завершения работы.• Если ThreadLocal не очищается вручную, объект остаётся в памяти, даже если он больше не нужен.remove()ThreadLocal<MyClass> threadLocal = ThreadLocal.withInitial(MyClass::new);
try {
MyClass obj = threadLocal.get();
// Логика
} finally {
threadLocal.remove(); // Очищаем объект
}
ThreadLocal осторожно, особенно в серверах с ThreadPool, чтобы избежать утечек памяти.#java #threadlocal #memoryleak
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2
Parallel Stream?Использование
parallelStream() может замедлить программу, если не учитывать его особенности.forEach().int[] sum = {0};
list.parallelStream().forEach(i -> sum[0] += i); // Потенциальная ошибка!reduce()int sum = list.parallelStream().reduce(0, Integer::sum);
parallelStream() эффективен, если объём данных большой и нет конкурентного доступа.#java #parallelstream #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤1
Closeable и AutoCloseableИнтерфейсы
Closeable и AutoCloseable предназначены для управления ресурсами, которые нужно явно закрывать после использования, например, потоки ввода-вывода, соединения с базами данных и т. д. Однако у них есть некоторые различия.1️⃣
AutoCloseable появился в Java 7 в связи с введением try-with-resources, это базовый интерфейс для всех ресурсов, которые могут быть автоматически закрыты.В
AutoCloseable определен метод:
void close() throws Exception;
То есть, метод
close() может выбрасывать любое исключение (Exception).2️⃣
Closeable наследует AutoCloseable, более специфичен и предназначен в основном для потоков ввода-вывода (I/O). В
Closeable метод close() может выбрасывать только IOException.#java #Closeable #AutoCloseable
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤1