Что такое ConcurrentHashMap в Java и чем он отличается от HashMap?
Пример
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);
map.put("B", 2);
map.forEach((k, v) -> {
System.out.println(k + " = " + v);
map.put("C", 3); // не вызовет ConcurrentModificationException
});
System.out.println(map);
}
}
Ответ
HashMap не является потокобезопасной: если несколько потоков одновременно изменяют её, возможны ошибки и ConcurrentModificationException.
ConcurrentHashMap — это потокобезопасная альтернатива, которая:
— позволяет одновременно читать и писать без полной блокировки всей карты
— делит данные на сегменты для повышения производительности
— гарантирует согласованность данных при многопоточном доступе
📌 Если работа только в одном потоке — можно использовать обычный HashMap. Если данные разделяются между потоками — правильнее брать ConcurrentHashMap.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🤯1
Please open Telegram to view this post
VIEW IN TELEGRAM
Exchanger — это синхронизатор из пакета java.util.concurrent, который позволяет двум потокам обмениваться данными в точке встречи. Каждый поток вызывает метод exchange(), и когда оба потока доходят до этой точки, они обмениваются переданными объектами.Это удобно, когда два потока должны координировать свои действия, передавая результаты вычислений друг другу.
• Позволяет безопасно обмениваться объектами между потоками
• Подходит для реализации producer-consumer моделей
• Удобен для синхронных этапов вычислений
import java.util.concurrent.Exchanger;
public class Main {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
Runnable producer = () -> {
try {
String data = "Данные от Producer";
System.out.println("Producer отправил: " + data);
String response = exchanger.exchange(data);
System.out.println("Producer получил: " + response);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Runnable consumer = () -> {
try {
String data = "Ответ от Consumer";
System.out.println("Consumer отправил: " + data);
String received = exchanger.exchange(data);
System.out.println("Consumer получил: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(producer).start();
new Thread(consumer).start();
}
}
👀 Exchanger особенно полезен, когда два потока выполняют разные задачи и должны регулярно обмениваться результатами — например, генератор данных и обработчик, или два этапа сложного расчёта.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
Покажу: Spring Test Profiler находит лишние перезапуски контекста и рассинхрон конфигов; унифицирую окружение, чиню кэш и ускоряю интеграц-тесты. Будет чек-лист.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13
Что такое WeakReference в Java и зачем она используется?
Пример
import java.lang.ref.WeakReference;
public class Main {
public static void main(String[] args) {
String strong = new String("Hello");
WeakReference<String> weak = new WeakReference<>(strong);
System.out.println("До GC: " + weak.get()); // ➔ Hello
strong = null;
System.gc(); // просим сборщик мусора освободить память
System.out.println("После GC: " + weak.get()); // ➔ null (объект мог быть удалён)
}
}
Ответ
WeakReference позволяет держать ссылку на объект, не мешая сборщику мусора его удалить. Как только на объект не остаётся сильных (обычных) ссылок, GC может освободить память, даже если есть WeakReference.
📌 Основные применения:
— кэши, где не критично хранить данные постоянно
— структуры, которые не должны мешать очистке памяти
— предотвращение утечек в долгоживущих коллекциях.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
DelayQueue — это потокобезопасная очередь из java.util.concurrent, где элементы становятся доступными только после истечения заданного времени задержки. Элементы должны реализовывать интерфейс Delayed.Она удобна для отложенной обработки задач — таймеров, кэшей с TTL, планировщиков.
• Элементы выдаются только после задержки
• Работает в многопоточном режиме
• Идеальна для задач с таймаутами
import java.util.concurrent.*;
class Task implements Delayed {
long start = System.currentTimeMillis() + 1000;
public long getDelay(TimeUnit u) { return u.convert(start - System.currentTimeMillis(), TimeUnit.MILLISECONDS); }
public int compareTo(Delayed o) { return Long.compare(getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS)); }
public String toString() { return "Задача выполнена"; }
}
public class Main {
public static void main(String[] args) throws Exception {
DelayQueue<Task> q = new DelayQueue<>();
q.put(new Task());
System.out.println(q.take()); // ждём 1 сек
}
}
👀 DelayQueue особенно полезна для отложенных задач, TTL-кэшей и планировщиков.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
Снова показываю как можно вести разработку «голыми руками» — без IDE, документации и даже интернета. На этот раз с помощью «пользовательской» Ubuntu Linux и OpenJDK.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13
Что такое ThreadLocal в Java и когда его стоит использовать?
Пример
public class Main {
private static final ThreadLocal<Integer> threadId =
ThreadLocal.withInitial(() -> (int) (Math.random() * 1000));
public static void main(String[] args) {
Runnable task = () ->
System.out.println(Thread.currentThread().getName() + " → " + threadId.get());
new Thread(task, "Поток-1").start();
new Thread(task, "Поток-2").start();
new Thread(task, "Поток-3").start();
}
}Ответ
ThreadLocal хранит данные отдельно для каждого потока. Даже если переменная одна, каждый поток получает свою копию.
📌 Применения:
— хранение пользовательских сессий в веб-приложениях
— уникальные ID запросов в логах
— объекты, которые нельзя шарить между потоками (например, SimpleDateFormat).
Но важно не забывать вызывать remove(), чтобы избежать утечек памяти в пуле потоков.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
PriorityBlockingQueue — это потокобезопасная очередь из java.util.concurrent, которая хранит элементы в отсортированном виде согласно их приоритету.Она активно используется в задачах, где нужно управлять порядком обработки — например, в планировщиках, системах обработки задач и диспетчерах потоков.
• Элементы автоматически сортируются
• Работает в многопоточном режиме
• Подходит для диспетчеризации задач по приоритету
import java.util.concurrent.PriorityBlockingQueue;
public class Main {
public static void main(String[] args) {
PriorityBlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
queue.add(5);
queue.add(1);
queue.add(3);
while (!queue.isEmpty()) {
System.out.println(queue.poll()); // ➔ 1, 3, 5
}
}
}
👀 PriorityBlockingQueue особенно полезна, когда задачи имеют приоритеты — например, обработка срочных запросов, планирование задач или распределение ресурсов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Мы знаем, как это бывает: проект на Java 8 живёт уже десятый год, релизить страшно, тестов мало, миграция пугает, а система критичная. И вот бизнес хочет «ускорить и не трогать».
Please open Telegram to view this post
VIEW IN TELEGRAM