Easy Java
5.22K subscribers
311 photos
51 videos
463 links
Лучшие обучающие материалы и другие полезности для Java-разработчиков.

Сотрудничество: @heywan_n1

Цены: @heywan_media

Реклама на бирже: https://telega.in/c/+r8kkGSypBY84MmIy
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
Ответ:
Anonymous Quiz
38%
1
52%
2
9%
3
2%
4
👩‍💻 Что такое AtomicInteger в Java и зачем он нужен?

AtomicInteger — это класс из пакета java.util.concurrent.atomic, который обеспечивает атомарные операции над целыми числами без использования synchronized.

Все операции (incrementAndGet, decrementAndGet, compareAndSet) выполняются потокобезопасно благодаря низкоуровневым механизмам процессора (CAS — Compare-And-Swap).


• Потокобезопасный счётчик без блокировок
• Быстрее, чем synchronized
• Подходит для высоконагруженных многопоточных систем

⚡️ Пример:

import java.util.concurrent.atomic.AtomicInteger;

public class Main {
private static final AtomicInteger counter = new AtomicInteger(0);

public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.incrementAndGet();
}
};

Thread t1 = new Thread(task);
Thread t2 = new Thread(task);

t1.start();
t2.start();

try {
t1.join();
t2.join();
} catch (InterruptedException ignored) {}

System.out.println("Результат: " + counter.get());
}
}


👀 AtomicInteger особенно полезен при подсчёте событий, генерации ID или создании неблокирующих структур данных, где важна скорость и потокобезопасность без тяжёлых блокировок.


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁15🔥7
Вопрос с собеса

Чем ReentrantLock отличается от synchronized в Java?

Пример🔽
import java.util.concurrent.locks.ReentrantLock;

public class Main {
private static final ReentrantLock lock = new ReentrantLock();
private static int counter = 0;

public static void main(String[] args) {
Runnable task = () -> {
lock.lock();
try {
counter++;
} finally {
lock.unlock();
}
};

new Thread(task).start();
new Thread(task).start();
}
}


Ответ🔽
ReentrantLock — это класс из java.util.concurrent.locks, который предоставляет больше возможностей, чем synchronized:

— Можно пытаться захватить блокировку с таймаутом (tryLock)
— Можно использовать блокировку с несколькими условиями (Condition)
— Можно вручную управлять моментом захвата и освобождения

📌 В отличие от synchronized, ReentrantLock требует явного вызова lock() и unlock(), что даёт гибкость, но требует дисциплины.


➡️ Easy Java | #Собес
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Please open Telegram to view this post
VIEW IN TELEGRAM
Ответ:
Anonymous Quiz
30%
1
43%
2
23%
3
4%
4
3
👩‍💻 Что такое CountDownLatch в Java и зачем он нужен?

CountDownLatch — это синхронизатор из пакета java.util.concurrent, который позволяет одному или нескольким потокам ждать, пока другие потоки завершат свои задачи.

Он инициализируется счётчиком, и каждый вызов countDown() уменьшает его на 1. Как только счётчик достигает нуля — все ожидающие потоки продолжают выполнение.


• Удобен для ожидания завершения группы потоков
• Позволяет синхронизировать старт или окончание работы
• Прост в использовании и потокобезопасен

⚡️ Пример:

import java.util.concurrent.CountDownLatch;

public class Main {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);

Runnable worker = () -> {
System.out.println(Thread.currentThread().getName() + " завершил работу");
latch.countDown();
};

new Thread(worker, "Поток 1").start();
new Thread(worker, "Поток 2").start();
new Thread(worker, "Поток 3").start();

latch.await(); // ждём, пока счётчик не станет 0
System.out.println("Все потоки завершили работу");
}
}


👀 CountDownLatch особенно полезен для синхронизации в тестах, многопоточных вычислениях и в случаях, когда нужно дождаться инициализации нескольких компонентов перед стартом основной логики.


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
👍3🔥1
Вопрос с собеса

Когда стоит использовать CopyOnWriteArrayList в Java?

Пример🔽
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class Main {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");

for (String s : list) {
list.add("C"); // не вызовет ConcurrentModificationException
}

System.out.println(list);
}
}


Ответ🔽
CopyOnWriteArrayList — это потокобезопасная реализация List, которая копирует весь массив при каждой модификации.

Она идеально подходит, когда:

— много операций чтения и мало операций записи
— нужно избежать ConcurrentModificationException при итерации
— важна простая потокобезопасность без внешней синхронизации

📌 Недостаток — высокая стоимость записи, так как создаётся новая копия массива при каждом изменении.


➡️ Easy Java | #Собес
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Please open Telegram to view this post
VIEW IN TELEGRAM
Ответ:
Anonymous Quiz
15%
1
72%
2
10%
3
4%
4
👩‍💻 Что такое CyclicBarrier в Java и зачем он нужен?

CyclicBarrier — это синхронизатор из пакета java.util.concurrent, который позволяет группе потоков дождаться друг друга, прежде чем продолжить выполнение.

В отличие от CountDownLatch, барьер можно использовать многократно — после того как все потоки достигли точки синхронизации, он сбрасывается и готов к новому циклу.


• Синхронизирует несколько потоков в «точках встречи»
• Можно выполнять дополнительное действие при достижении барьера
• Подходит для повторяющихся этапов работы в параллельных задачах

⚡️ Пример:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Main {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("Все потоки достигли барьера, продолжаем!")
);

Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " готов");
barrier.await();
System.out.println(Thread.currentThread().getName() + " продолжает работу");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
};

new Thread(task, "Поток 1").start();
new Thread(task, "Поток 2").start();
new Thread(task, "Поток 3").start();
}
}


👀 CyclicBarrier особенно полезен, когда несколько потоков должны синхронизировать свои шаги — например, в параллельных алгоритмах, симуляциях, или играх с одновременным обновлением состояния.


➡️ Easy Java | #Теория
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Вопрос с собеса

В чём разница между ExecutorService и ForkJoinPool в Java?

Пример🔽
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class Main {
public static void main(String[] args) {
// Пример с ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("Задача в ExecutorService"));
executor.shutdown();

// Пример с ForkJoinPool
ForkJoinPool pool = new ForkJoinPool();
int sum = pool.invoke(new SumTask(1, 5));
System.out.println("Сумма: " + sum);
}

static class SumTask extends RecursiveTask<Integer> {
int start, end;

SumTask(int start, int end) {
this.start = start;
this.end = end;
}

@Override
protected Integer compute() {
if (end - start <= 1) {
return start + end;
}
int mid = (start + end) / 2;
SumTask left = new SumTask(start, mid);
SumTask right = new SumTask(mid + 1, end);
left.fork();
return right.compute() + left.join();
}
}
}


Ответ🔽
ExecutorService — это абстракция для управления пулом потоков и выполнения задач (Runnable или Callable) в очереди. Он отлично подходит для стандартных многопоточных задач, где нужно управлять количеством потоков и временем жизни пула.

ForkJoinPool — это специальная реализация ExecutorService, оптимизированная для задач типа divide-and-conquer, где задачи рекурсивно делятся на подзадачи (через RecursiveTask или RecursiveAction) и выполняются с помощью алгоритма "work-stealing".

📌 Если задачи независимые и нет сложного деления — хватит обычного ExecutorService. Если нужна параллельная рекурсия и максимальная загрузка процессоров — лучше ForkJoinPool.


➡️ Easy Java | #Собес
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM