synchronized?Ключевое слово
synchronized используется для управления доступом к разделяемым ресурсам в многопоточном окружении.📌 Пример использования:
1️⃣ Синхронизация метода:
public synchronized void increment() {
count++;
}2️⃣ Синхронизация блока кода:
public void increment() {
synchronized (this) {
count++;
}
}• Обеспечивает монопольный доступ к методу или блоку.
• Снижает производительность из-за блокировок.
synchronized только там, где это действительно необходимо, чтобы избежать узких мест.#java #synchronized #multithreading
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤1
volatile и synchronized Lazy Initialization — это паттерн, при котором объект создаётся только при первом обращении к нему, а не в момент запуска приложения. Это полезно для оптимизации производительности, особенно если объект может быть дорогим в создании, а его использование не всегда необходимо.
В Java можно реализовать Lazy Initialization с помощью ключевого слова
volatile и синхронизации (synchronized), чтобы гарантировать правильное поведение в многозадачных приложениях.📌 Что такое
volatile и synchronized? 1️⃣
volatile: Гарантирует, что все потоки видят актуальное значение переменной, без кэширования её в локальной памяти. 2️⃣
synchronized: Блокирует доступ к коду, чтобы только один поток мог выполнить его в определённый момент времени.Пример:
public class LazyInitialization {
// Переменная с модификатором volatile
private static volatile SomeClass instance;
// Метод для получения экземпляра класса
public static SomeClass getInstance() {
// Первый контроль (без блокировки), если объект уже инициализирован
if (instance == null) {
synchronized (LazyInitialization.class) {
// Второй контроль с блокировкой для создания объекта
if (instance == null) {
instance = new SomeClass();
}
}
}
return instance;
}
public static void main(String[] args) {
SomeClass obj = LazyInitialization.getInstance();
System.out.println(obj);
}
}
class SomeClass {
// Пример класса для инициализации
public SomeClass() {
System.out.println("Объект SomeClass создан!");
}
}
📌 Как это работает:
1️⃣ При первом обращении к
getInstance(), проверяется, создан ли уже объект. Если нет — блокируется доступ для других потоков с помощью synchronized. 2️⃣ Внутри блока
synchronized снова проверяется, не был ли объект создан другим потоком, чтобы избежать повторной инициализации. 3️⃣
volatile гарантирует, что создание объекта будет завершено до того, как другие потоки получат доступ к переменной.📌 Когда использовать такую реализацию?
- Для обеспечения потокобезопасности при ленивой инициализации объектов.
- В многозадачных приложениях, где объект должен быть создан только один раз.
💡 Совет: Эта техника подходит для случаев, когда объект может быть дорогим в создании и его создание должно происходить только при первом обращении.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2👎1🔥1
StringBuilder и StringBufferИ
StringBuilder, и StringBuffer используются для работы со строками, но между ними есть важные отличия.✔️ StringBuilder быстрее, но не потокобезопасен.
✔️ StringBuffer потокобезопасен, но медленнее из-за синхронизации.
StringBuilder:StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Hello WorldStringBuffer:StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Hello WorldStringBuilder для лучшей производительности.#java #stringbuilder #stringbuffer
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18❤3🔥2
DatagramChannel из java.nio.channels — это мощный инструмент для работы с UDP-соединениями в Java. Этот канал позволяет отправлять и принимать датаграммы (пакеты данных), что делает его идеальным для создания лёгких и быстрых сетевых приложений. 🔍 Особенности DatagramChannel:
1️⃣ Поддерживает неблокирующий режим.
2️⃣ Простое взаимодействие без установки соединения.
3️⃣ Отлично подходит для передачи небольших сообщений.
📌 Пример отправки и получения сообщения:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
public class DatagramChannelExample {
public static void main(String[] args) {
new Thread(() -> {
// Создаём канал для получения
try (DatagramChannel receiver = DatagramChannel.open()) {
receiver.bind(new InetSocketAddress(9999));
ByteBuffer buffer = ByteBuffer.allocate(1024);
receiver.receive(buffer);
buffer.flip();
byte[] receivedData = new byte[buffer.limit()];
buffer.get(receivedData);
System.out.println("Получено сообщение: " + new String(receivedData));
} catch (IOException e) {
throw new RuntimeException(e);
}
}).start();
// Создаём канал для отправки
try (DatagramChannel sender = DatagramChannel.open()) {
String message = "Привет, мир!";
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
sender.send(buffer, new InetSocketAddress("localhost", 9999));
System.out.println("Сообщение отправлено.");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
🔗 Ключевые моменты:
1️⃣ Отправка: Используйте
send для передачи данных по указанному адресу. 2️⃣ Получение: Метод
receive позволяет читать входящие датаграммы. 3️⃣ Порт: Убедитесь, что отправитель и получатель используют один и тот же порт.
✨ Когда использовать?
- Для приложений с низкой задержкой, где важна скорость.
- Для отправки сообщений в локальной сети.
- В системах, где не требуется постоянное соединение.
💡 Совет: Используйте
DatagramChannel для лёгких и быстрых решений, например, для игровых серверов или мониторинга систем. #Java #DatagramChannel #UDP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤4🔥3👏1
var и когда его использовать?С появлением Java 10 был добавлен
var – ключевое слово для вывода типа переменной на основе присвоенного значения.• Позволяет сократить код, убрав явное указание типа.• Работает только для локальных переменных (нельзя использовать для аргументов метода или полей класса).
var message = "Hello, Java!"; // Компилятор автоматически определит тип String
var number = 42; // int
var list = List.of("A", "B", "C"); // List<String>
var так:
var x; // Ошибка, требуется инициализация
var, если тип очевиден, но не злоупотребляйте, чтобы не терять читаемость кода.#java #var #java10
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤1👎1
Record в Java?Record – это новый тип класса, который появился в Java 14 и предназначен для создания неизменяемых объектов с минимальным кодом.• Автоматически создаёт equals(), hashCode() и toString().• Подходит для DTO (Data Transfer Object) и неизменяемых объектов.public record Person(String name, int age) {}
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
System.out.println(person); // Person[name=Alice, age=30]
}
}Record, если вам нужен неизменяемый объект с автогенерацией методов.#java #record #java14
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2
WeakReference?WeakReference – это специальный тип ссылки, который не предотвращает сборщик мусора от удаления объекта.• Используется, когда объект не является критически важным.• Полезен для кеширования, где объект можно освободить при нехватке памяти.
import java.lang.ref.WeakReference;
public class WeakRefExample {
public static void main(String[] args) {
String str = new String("WeakReference");
WeakReference<String> weakRef = new WeakReference<>(str);
str = null; // Теперь объект доступен для GC
System.gc();
System.out.println(weakRef.get()); // Может быть null
}
}
WeakReference, если объект должен автоматически удаляться при нехватке памяти.#java #weakreference
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍2🔥1🙏1
💡 Как управлять потоками с помощью 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