Утечка памяти в Java
Утечка памяти — это состояние в приложении, когда объекты, которые больше не используются, продолжают оставаться в памяти, не подлежащие сборке мусора. В отличие от традиционных языков программирования, таких как C/C++, Java имеет встроенный сборщик мусора (Garbage Collector), который автоматически освобождает память, занятую ненужными объектами. Однако это не гарантирует, что утечки памяти полностью исключены.
В Java утечки памяти случаются, когда объекты, которые больше не нужны программе, имеют сильные ссылки и не могут быть удалены сборщиком мусора. Это приводит к постепенному увеличению использования памяти и, как следствие, к ухудшению производительности или даже к OutOfMemoryError. В этой статье мы рассмотрим, что представляет собой утечка памяти в Java, каковы её причины, как её обнаружить и предотвратить.
1. Что такое утечка памяти в Java?
Утечка памяти в Java происходит, когда приложение продолжает хранить ссылки на ненужные объекты. Эти объекты становятся неподходящими для сборки мусора, и их память не освобождается, несмотря на отсутствие практического использования. Такая ситуация может возникать по нескольким причинам: неправильное использование коллекций, постоянные ссылки на анонимные или вложенные классы, ошибки при обработке потоков и многое другое.
Пример классической утечки памяти:
2. Виды утечек памяти в Java
Утечки памяти в Java можно классифицировать на несколько основных типов:
2.1 Постепенная утечка (Heap Leaks)
Этот тип утечки возникает, когда объекты продолжают оставаться в памяти, даже если они больше не используются. Например, большие коллекции, которые постепенно увеличиваются и никогда не очищаются.
2.2 Утечка в статических полях (Static Field Leaks)
Статические поля живут на протяжении всего времени работы приложения и, если на объект ссылается статическое поле, объект также не подлежит сборке мусора.
2.3 Утечка в слушателях (Listener Leaks)
Этот тип утечки происходит, когда слушатели (listeners) или наблюдатели (observers) не удаляются после завершения работы. Например, при использовании событийных моделей или слушателей интерфейсов (GUI-компоненты, потоки).
#Java #Training #Medium #Memory_Leak
Утечка памяти — это состояние в приложении, когда объекты, которые больше не используются, продолжают оставаться в памяти, не подлежащие сборке мусора. В отличие от традиционных языков программирования, таких как C/C++, Java имеет встроенный сборщик мусора (Garbage Collector), который автоматически освобождает память, занятую ненужными объектами. Однако это не гарантирует, что утечки памяти полностью исключены.
В Java утечки памяти случаются, когда объекты, которые больше не нужны программе, имеют сильные ссылки и не могут быть удалены сборщиком мусора. Это приводит к постепенному увеличению использования памяти и, как следствие, к ухудшению производительности или даже к OutOfMemoryError. В этой статье мы рассмотрим, что представляет собой утечка памяти в Java, каковы её причины, как её обнаружить и предотвратить.
1. Что такое утечка памяти в Java?
Утечка памяти в Java происходит, когда приложение продолжает хранить ссылки на ненужные объекты. Эти объекты становятся неподходящими для сборки мусора, и их память не освобождается, несмотря на отсутствие практического использования. Такая ситуация может возникать по нескольким причинам: неправильное использование коллекций, постоянные ссылки на анонимные или вложенные классы, ошибки при обработке потоков и многое другое.
Пример классической утечки памяти:
import java.util.ArrayList;
import java.util.List;
public class MemoryLeakExample {
private static List<Object> list = new ArrayList<>();
public static void main(String[] args) {
// Создаем утечку памяти, добавляя объекты в список, но никогда их не удаляя
while (true) {
list.add(new Object());
}
}
}
В этом примере список list продолжает расти, так как новые объекты постоянно добавляются, но никогда не удаляются. В итоге программа столкнется с OutOfMemoryError.
2. Виды утечек памяти в Java
Утечки памяти в Java можно классифицировать на несколько основных типов:
2.1 Постепенная утечка (Heap Leaks)
Этот тип утечки возникает, когда объекты продолжают оставаться в памяти, даже если они больше не используются. Например, большие коллекции, которые постепенно увеличиваются и никогда не очищаются.
public class GradualMemoryLeak {
private static List<String> cache = new ArrayList<>();
public void addData() {
for (int i = 0; i < 1000; i++) {
cache.add("Data-" + i);
}
}
}
Если метод addData вызывается многократно без очистки списка cache, то список будет постоянно увеличиваться, вызывая утечку памяти.
2.2 Утечка в статических полях (Static Field Leaks)
Статические поля живут на протяжении всего времени работы приложения и, если на объект ссылается статическое поле, объект также не подлежит сборке мусора.
public class StaticFieldMemoryLeak {
private static List<Object> staticList = new ArrayList<>();
public void addObject(Object obj) {
staticList.add(obj);
}
}
Здесь статическое поле staticList сохраняет все добавленные объекты, и они никогда не удаляются, что приводит к утечке памяти.
2.3 Утечка в слушателях (Listener Leaks)
Этот тип утечки происходит, когда слушатели (listeners) или наблюдатели (observers) не удаляются после завершения работы. Например, при использовании событийных моделей или слушателей интерфейсов (GUI-компоненты, потоки).
public class EventListenerMemoryLeak {
public static void main(String[] args) {
JFrame frame = new JFrame("Example");
JButton button = new JButton("Click Me");
button.addActionListener(e -> System.out.println("Button clicked!"));
frame.add(button);
frame.setSize(200, 200);
frame.setVisible(true);
// Закрываем окно, но слушатель остается в памяти
frame.dispose();
}
}
В этом примере, если не удалить слушатели ActionListener перед dispose(), объект button и все связанные объекты будут продолжать удерживаться в памяти.
#Java #Training #Medium #Memory_Leak
2.4 Утечка в потоках (Thread Leaks)
Когда потоки продолжают выполняться или ожидают события, они могут удерживать ссылки на объекты. Например, использование ThreadLocal или неправильное завершение потоков.
3. Методы обнаружения утечек памяти
Для диагностики и предотвращения утечек памяти в Java можно использовать несколько методов:
Профайлеры: Инструменты, такие как VisualVM, Eclipse MAT, и JProfiler, позволяют отслеживать использование памяти и находить объекты, которые занимают много места.
Анализ дампа памяти (Heap Dump): Дамп памяти представляет собой снимок текущего состояния кучи JVM. Его можно проанализировать с помощью jmap или инструментов, таких как Eclipse MAT.
Инструменты для мониторинга: Использование jconsole, jvisualvm или других инструментов для мониторинга позволяет наблюдать за временем жизни объектов и отслеживать изменения.
Пример использования jmap для создания дампа памяти:
4. Способы предотвращения утечек памяти
Чтобы предотвратить утечки памяти в Java, рекомендуется следовать следующим принципам:
Удаление ненужных ссылок:
Освобождайте ссылки на объекты, как только они больше не нужны.
Избегайте использования статических полей для временных объектов:
Статические поля сохраняют объекты на протяжении всего времени работы приложения.
Удаление слушателей:
Удаляйте слушатели (listeners) и наблюдатели (observers), когда они больше не нужны.
Использование WeakReference и SoftReference:
Для объектов, которые можно удалять при недостатке памяти, используйте слабые и мягкие ссылки.
Проверка потоков:
Убедитесь, что потоки завершаются корректно и не продолжают работать, удерживая ненужные ссылки.
Применение try-with-resources:
Использование try-with-resources для закрытия ресурсов, таких как потоки и соединения, предотвращает утечки ресурсов.
Пример корректного использования try-with-resources:
#Java #Training #Medium #Memory_Leak
Когда потоки продолжают выполняться или ожидают события, они могут удерживать ссылки на объекты. Например, использование ThreadLocal или неправильное завершение потоков.
public class ThreadMemoryLeak {
public void createThread() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(10000); // Ожидание в течение длительного времени
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
}
}
Если потоки создаются многократно и не завершаются корректно, то их память будет постепенно заполняться.
3. Методы обнаружения утечек памяти
Для диагностики и предотвращения утечек памяти в Java можно использовать несколько методов:
Профайлеры: Инструменты, такие как VisualVM, Eclipse MAT, и JProfiler, позволяют отслеживать использование памяти и находить объекты, которые занимают много места.
Анализ дампа памяти (Heap Dump): Дамп памяти представляет собой снимок текущего состояния кучи JVM. Его можно проанализировать с помощью jmap или инструментов, таких как Eclipse MAT.
Инструменты для мониторинга: Использование jconsole, jvisualvm или других инструментов для мониторинга позволяет наблюдать за временем жизни объектов и отслеживать изменения.
Пример использования jmap для создания дампа памяти:
jmap -dump:format=b,file=heap_dump.hprof <PID>
4. Способы предотвращения утечек памяти
Чтобы предотвратить утечки памяти в Java, рекомендуется следовать следующим принципам:
Удаление ненужных ссылок:
Освобождайте ссылки на объекты, как только они больше не нужны.
Избегайте использования статических полей для временных объектов:
Статические поля сохраняют объекты на протяжении всего времени работы приложения.
Удаление слушателей:
Удаляйте слушатели (listeners) и наблюдатели (observers), когда они больше не нужны.
Использование WeakReference и SoftReference:
Для объектов, которые можно удалять при недостатке памяти, используйте слабые и мягкие ссылки.
Проверка потоков:
Убедитесь, что потоки завершаются корректно и не продолжают работать, удерживая ненужные ссылки.
Применение try-with-resources:
Использование try-with-resources для закрытия ресурсов, таких как потоки и соединения, предотвращает утечки ресурсов.
Пример корректного использования try-with-resources:
import java.io.*;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
System.out.println(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
В этом примере ресурс автоматически закрывается, даже если возникает исключение.
#Java #Training #Medium #Memory_Leak
Недавнее обсуждение многопоточности в нашем чате, подтолкнуло меня восполнить недостатки знаний в этой области Java. 🧐
Дополняю темы про распространенные ошибки многопоточности.
Распространенные ошибки многопоточности
Race Condition (Состояние гонки)
Race Condition — это ситуация, когда поведение программы зависит от порядка или своевременности выполнения потоков. Оно возникает, когда несколько потоков одновременно обращаются к одному и тому же ресурсу (например, переменной или объекту), и хотя бы один из них изменяет его.
Пример Race Condition:
Почему Race Condition?
count++ не является атомарной операцией.
Она состоит из трех шагов:
Чтение текущего значения count.
Увеличение значения.
Запись нового значения обратно в переменную.
Если оба потока прочитают одно и то же значение до записи, итоговое значение будет некорректным.
Deadlock (Взаимная блокировка)
Deadlock — ситуация, при которой два или более потоков блокируют друг друга, ожидая освобождения ресурсов.
Пример Deadlock:
Что происходит:
Поток 1 захватывает lock1 и ждет lock2.
Поток 2 захватывает lock2 и ждет lock1.
Оба потока застревают, ожидая освобождения ресурсов друг от друга.
#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Дополняю темы про распространенные ошибки многопоточности.
Распространенные ошибки многопоточности
Race Condition (Состояние гонки)
Race Condition — это ситуация, когда поведение программы зависит от порядка или своевременности выполнения потоков. Оно возникает, когда несколько потоков одновременно обращаются к одному и тому же ресурсу (например, переменной или объекту), и хотя бы один из них изменяет его.
Пример Race Condition:
public class Counter {
private int count = 0;
public void increment() {
count++; // Неатомарная операция: чтение, увеличение, запись
}
public int getCount() {
return count;
}
}
public class RaceConditionExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final count: " + counter.getCount()); // Ожидаем 2000, но результат может быть меньше
}
}
Почему Race Condition?
count++ не является атомарной операцией.
Она состоит из трех шагов:
Чтение текущего значения count.
Увеличение значения.
Запись нового значения обратно в переменную.
Если оба потока прочитают одно и то же значение до записи, итоговое значение будет некорректным.
Deadlock (Взаимная блокировка)
Deadlock — ситуация, при которой два или более потоков блокируют друг друга, ожидая освобождения ресурсов.
Пример Deadlock:
public class DeadlockExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock1...");
try { Thread.sleep(50); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("Thread 1: Acquired lock2.");
}
}
}
public void method2() {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock2...");
try { Thread.sleep(50); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("Thread 2: Acquired lock1.");
}
}
}
public static void main(String[] args) {
DeadlockExample demo = new DeadlockExample();
Thread t1 = new Thread(demo::method1);
Thread t2 = new Thread(demo::method2);
t1.start();
t2.start();
}
}
Что происходит:
Поток 1 захватывает lock1 и ждет lock2.
Поток 2 захватывает lock2 и ждет lock1.
Оба потока застревают, ожидая освобождения ресурсов друг от друга.
#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Livelock (Живая блокировка)
Livelock похож на Deadlock, но здесь потоки не блокируются, а продолжают изменять свое состояние в попытке избежать конфликта, не продвигаясь дальше.
Пример Livelock:
Что происходит:
Оба потока продолжают "уступать" друг другу, не завершив работу.
Starvation (Голодание)
Starvation — ситуация, когда поток постоянно лишается доступа к ресурсу из-за того, что другие потоки с более высоким приоритетом занимают его.
Причина: Использование приоритетов потоков, где высокоприоритетные потоки блокируют низкоприоритетные.
Thread Interference (Конфликт потоков)
Это ситуация, похожая на Race Condition, когда несколько потоков одновременно читают и изменяют общие данные, приводя к непредсказуемым результатам.
Пример:
Потоки выполняют операции на одной переменной без синхронизации, что приводит к некорректным итоговым значениям.
Memory Consistency Errors (Ошибки согласованности памяти)
Эти ошибки возникают, когда один поток изменяет данные, но другие потоки видят устаревшее состояние этих данных.
Причина: Использование кэша процессора.
Переменная, измененная в одном потоке, может не быть видимой для других потоков.
Решение:
Использование volatile для обеспечения видимости изменений.
Как предотвратить ошибки многопоточности
Использование синхронизации:
synchronized блоки или методы.
ReentrantLock для более гибкого управления блокировкой.
Использование атомарных типов:
Классы из пакета java.util.concurrent.atomic:
AtomicInteger, AtomicBoolean, AtomicReference.
Использование высокоуровневых утилит:
ExecutorService для управления потоками.
CountDownLatch, Semaphore, CyclicBarrier.
Избегание Deadlock:
Всегда захватывать блокировки в одном и том же порядке.
Использование таймаутов при ожидании захвата.
Проверка и отладка:
Инструменты отладки (например, jstack, VisualVM) для анализа состояния потоков.
Логирование текущих блокировок и их владельцев.
#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Livelock похож на Deadlock, но здесь потоки не блокируются, а продолжают изменять свое состояние в попытке избежать конфликта, не продвигаясь дальше.
Пример Livelock:
public class LivelockExample {
static class Worker {
private boolean active = true;
public synchronized void work(Worker other) {
while (active) {
System.out.println(Thread.currentThread().getName() + " is working...");
try { Thread.sleep(50); } catch (InterruptedException e) {}
if (other.isActive()) {
System.out.println(Thread.currentThread().getName() + " is waiting...");
continue;
}
break;
}
}
public synchronized void setActive(boolean active) {
this.active = active;
}
public synchronized boolean isActive() {
return active;
}
}
public static void main(String[] args) {
Worker w1 = new Worker();
Worker w2 = new Worker();
Thread t1 = new Thread(() -> w1.work(w2), "Worker 1");
Thread t2 = new Thread(() -> w2.work(w1), "Worker 2");
t1.start();
t2.start();
}
}
Что происходит:
Оба потока продолжают "уступать" друг другу, не завершив работу.
Starvation (Голодание)
Starvation — ситуация, когда поток постоянно лишается доступа к ресурсу из-за того, что другие потоки с более высоким приоритетом занимают его.
Причина: Использование приоритетов потоков, где высокоприоритетные потоки блокируют низкоприоритетные.
Thread Interference (Конфликт потоков)
Это ситуация, похожая на Race Condition, когда несколько потоков одновременно читают и изменяют общие данные, приводя к непредсказуемым результатам.
Пример:
Потоки выполняют операции на одной переменной без синхронизации, что приводит к некорректным итоговым значениям.
Memory Consistency Errors (Ошибки согласованности памяти)
Эти ошибки возникают, когда один поток изменяет данные, но другие потоки видят устаревшее состояние этих данных.
Причина: Использование кэша процессора.
Переменная, измененная в одном потоке, может не быть видимой для других потоков.
Решение:
Использование volatile для обеспечения видимости изменений.
private static volatile boolean running = true;
public void run() {
while (running) {
// Выполняем задачу
}
}
Как предотвратить ошибки многопоточности
Использование синхронизации:
synchronized блоки или методы.
ReentrantLock для более гибкого управления блокировкой.
Использование атомарных типов:
Классы из пакета java.util.concurrent.atomic:
AtomicInteger, AtomicBoolean, AtomicReference.
Использование высокоуровневых утилит:
ExecutorService для управления потоками.
CountDownLatch, Semaphore, CyclicBarrier.
Избегание Deadlock:
Всегда захватывать блокировки в одном и том же порядке.
Использование таймаутов при ожидании захвата.
Проверка и отладка:
Инструменты отладки (например, jstack, VisualVM) для анализа состояния потоков.
Логирование текущих блокировок и их владельцев.
#Java #Training #Multithreading #Medium #Race_Condition #Livelock #Starvation #Thread_Interference #Memory_Consistency_Errors #Multithreading_errors
Анонсирую новую рубрику!
Теперь по субботам я буду публиковать ссылки на материалы которые Вы, возможно пропустили за неделю!
Итак:
С 05.05 по 09.05
Jackson: Ключевые аннотации для сериализации
Jackson: Аннотации Jackson для десериализации и изменения структуры JSON
Jackson: работа со списками, картами и вложенными объектами
Jackson: кастомные десериализаторы
Jackson: глобальная настройка ObjectMapper: как управлять сериализацией и десериализацией
Использование модулей в Jackson: JavaTimeModule и работа с Java 8 датами
Jackson: частичная сериализация с помощью @JsonView
Jackson: Tree Model и Streaming API в Jackson: когда нужна гибкость и производительность
Полезная статья: Программирование без условных операторов
Как и всегда, задачи можно найти под тегом - #Tasks, мемы - #Mems
#memory
Теперь по субботам я буду публиковать ссылки на материалы которые Вы, возможно пропустили за неделю!
Итак:
С 05.05 по 09.05
Jackson: Ключевые аннотации для сериализации
Jackson: Аннотации Jackson для десериализации и изменения структуры JSON
Jackson: работа со списками, картами и вложенными объектами
Jackson: кастомные десериализаторы
Jackson: глобальная настройка ObjectMapper: как управлять сериализацией и десериализацией
Использование модулей в Jackson: JavaTimeModule и работа с Java 8 датами
Jackson: частичная сериализация с помощью @JsonView
Jackson: Tree Model и Streaming API в Jackson: когда нужна гибкость и производительность
Полезная статья: Программирование без условных операторов
Как и всегда, задачи можно найти под тегом - #Tasks, мемы - #Mems
#memory
С 10.05 по 16.05
Следующая неделя
Воскресный мотивационный пост: Почему все-таки программирование?
Примитивные типы данных в Java
Глубокое изучение типа данных byte в Java
Полный разбор примитивного типа int в Java
Gson: основы сериализации и десериализации
Базовая десериализация и аннотации в Gson
Авторская статья: Самые пугающие три точки кода. Varargs в Java
Полезные статьи и видео:
Идемпотентность и зачем она
Первые шаги в Spring Security с JWT
И посмеяться, тем кто знает английский
Как и всегда, задачи можно найти под тегом - #Tasks, мемы - #Mems
#memory
Следующая неделя
Воскресный мотивационный пост: Почему все-таки программирование?
Примитивные типы данных в Java
Глубокое изучение типа данных byte в Java
Полный разбор примитивного типа int в Java
Gson: основы сериализации и десериализации
Базовая десериализация и аннотации в Gson
Авторская статья: Самые пугающие три точки кода. Varargs в Java
Полезные статьи и видео:
Идемпотентность и зачем она
Первые шаги в Spring Security с JWT
И посмеяться, тем кто знает английский
Как и всегда, задачи можно найти под тегом - #Tasks, мемы - #Mems
#memory
С 17.05 по 23.05
Предыдущий пост(с 10.05 по 16.05)
Следующая неделя
Воскресный мотивационный пост:
Как заставить себя учиться?🤓
Запись встреч
Controllers in Spring. Разбираем создание и устройство.
Обучающие статьи
Глубокое изучение типа данных short в Java
Глубокое изучение типа данных long в Java
Работа с коллекциями, вложенными объектами и generic-типами в Gson
Кастомизация и адаптеры в Gson
Работа с JsonElement и полезные советы в Gson
Полезные статьи и видео:
«Голая Java» или разработка без всего
Глубокое погружение в процедуру запуска JVM
Простое руководство по самой универсальной разметке - Markdown
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Предыдущий пост(с 10.05 по 16.05)
Следующая неделя
Воскресный мотивационный пост:
Как заставить себя учиться?
Запись встреч
Controllers in Spring. Разбираем создание и устройство.
Обучающие статьи
Глубокое изучение типа данных short в Java
Глубокое изучение типа данных long в Java
Работа с коллекциями, вложенными объектами и generic-типами в Gson
Кастомизация и адаптеры в Gson
Работа с JsonElement и полезные советы в Gson
Полезные статьи и видео:
«Голая Java» или разработка без всего
Глубокое погружение в процедуру запуска JVM
Простое руководство по самой универсальной разметке - Markdown
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Please open Telegram to view this post
VIEW IN TELEGRAM
С 24.05 по 31.05
Предыдущий пост(с 17.05 по 23.05)
Следующая неделя
Воскресный мотивационный пост:
"Твой первый проект — важнее, чем думаешь"
Выбранная голосованием тема:
Паттерны проектирования на Java: суть, история и применение
Запись встреч:
Изучаем Swagger
Обучающие статьи:
Глубокое изучение типа данных double в Java
Глубокое изучение типа float в Java
Глубокое изучение типа данных char в Java
Введение в Liquibase
Структура и основные команды Liquibase
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!🥳
Авторские статьи:
Как я память искал (Часть I)
Как я память искал (Часть II)
Полезные статьи и видео:
Управление транзакциями в Spring: подробно о @Transactional
Делаем свою простейшую систему сборки для Java
Проблема N+1 в Hibernate — ВСЕ СПОСОБЫ решения
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Предыдущий пост(с 17.05 по 23.05)
Следующая неделя
Воскресный мотивационный пост:
"Твой первый проект — важнее, чем думаешь"
Выбранная голосованием тема:
Паттерны проектирования на Java: суть, история и применение
Запись встреч:
Изучаем Swagger
Обучающие статьи:
Глубокое изучение типа данных double в Java
Глубокое изучение типа float в Java
Глубокое изучение типа данных char в Java
Введение в Liquibase
Структура и основные команды Liquibase
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!
Авторские статьи:
Как я память искал (Часть I)
Как я память искал (Часть II)
Полезные статьи и видео:
Управление транзакциями в Spring: подробно о @Transactional
Делаем свою простейшую систему сборки для Java
Проблема N+1 в Hibernate — ВСЕ СПОСОБЫ решения
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Please open Telegram to view this post
VIEW IN TELEGRAM
С 31.05 по 06.06
Предыдущий пост(с 24.05 по 30.05)
Следующая неделя
Воскресный мотивационный пост:
«Ты не программируешь — ты притворяешься, что учишься»
Выбранная голосованием тема:
Архитектурный шаблон MVC в Java Spring: теория, правила, ошибки
Запись встреч:
Многопоточка во всей красе. Часть 1.
Обучающие статьи:
Типы changesets и стратегии развертывания в Liquibase
Откаты (Rollback) и теги в Liquibase
Интеграция Liquibase с другими инструментами
Глубокое изучение типа данных boolean в Java
Ссылочные типы данных в Java
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!🥳
Авторская статья (которая кому-то не понравилась):
Пагинация, которую начинаешь ненавидеть😵
Полезные статьи и видео:
Создаём HTTP-сервер на Java NIO
Большой гайд. Пишем микросервисы на Java и Spring Boot, заворачиваем в Docker, запускаем на EKS, мониторим на Grafana
ИСТОРИЯ НЕЙРОСЕТЕЙ - ОТ ПЕРЦЕПТРОНА ДО CHATGPT
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Предыдущий пост(с 24.05 по 30.05)
Следующая неделя
Воскресный мотивационный пост:
«Ты не программируешь — ты притворяешься, что учишься»
Выбранная голосованием тема:
Архитектурный шаблон MVC в Java Spring: теория, правила, ошибки
Запись встреч:
Многопоточка во всей красе. Часть 1.
Обучающие статьи:
Типы changesets и стратегии развертывания в Liquibase
Откаты (Rollback) и теги в Liquibase
Интеграция Liquibase с другими инструментами
Глубокое изучение типа данных boolean в Java
Ссылочные типы данных в Java
Пост под которым нет поздравлений:
Сегодня каналу исполнился год!
Авторская статья (которая кому-то не понравилась):
Пагинация, которую начинаешь ненавидеть
Полезные статьи и видео:
Создаём HTTP-сервер на Java NIO
Большой гайд. Пишем микросервисы на Java и Spring Boot, заворачиваем в Docker, запускаем на EKS, мониторим на Grafana
ИСТОРИЯ НЕЙРОСЕТЕЙ - ОТ ПЕРЦЕПТРОНА ДО CHATGPT
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Please open Telegram to view this post
VIEW IN TELEGRAM
С 07.06 по 13.06
Предыдущий пост(с 31.05 по 06.06)
Воскресный мотивационный пост:
«Обучение Java — марафон, а не прыжок с трамплина»
Выбранная голосованием тема:
JavaMailSender в Spring Boot
Запись встреч:
Многопоточка во всей красе. Часть 2.
Обучающие статьи:
Объекты в Java
Ссылочные типы в Java — массивы
Ссылочные типы в Java — строки (String)
Введение в Flyway
Настройка и базовые команды Flyway
Пост о воспоминаниях:
Как мы писали крестики - нолики
Полезные статьи и видео:
Библиотека для кэширования Caffeine: анализ кода
Spring Data JPA и Hibernate: ориентируемся на производительность. Часть 1
Часть 1: Как я создал идеальный REST API — микросервис инцидентов на Java и Spring
Для тех кто знает английский - посмеяться
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory
Предыдущий пост(с 31.05 по 06.06)
Воскресный мотивационный пост:
«Обучение Java — марафон, а не прыжок с трамплина»
Выбранная голосованием тема:
JavaMailSender в Spring Boot
Запись встреч:
Многопоточка во всей красе. Часть 2.
Обучающие статьи:
Объекты в Java
Ссылочные типы в Java — массивы
Ссылочные типы в Java — строки (String)
Введение в Flyway
Настройка и базовые команды Flyway
Пост о воспоминаниях:
Как мы писали крестики - нолики
Полезные статьи и видео:
Библиотека для кэширования Caffeine: анализ кода
Spring Data JPA и Hibernate: ориентируемся на производительность. Часть 1
Часть 1: Как я создал идеальный REST API — микросервис инцидентов на Java и Spring
Для тех кто знает английский - посмеяться
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
#memory