Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Пакет java.util.concurrent
Пакет java.util.concurrent — это стандартная библиотека Java для многопоточного программирования. Она предоставляет высокоуровневые инструменты вместо работы с низкоуровневыми потоками и синхронизацией.
1. ExecutorService и Thread Pools
ExecutorService управляет пулом потоков. Вместо создания потоков вручную:
// Плохо: создаём потоки вручную
for (Task task : tasks) {
new Thread(task).start();
}
// Хорошо: используем ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(10);
for (Task task : tasks) {
executor.submit(task);
}
executor.shutdown();
Примеры:
newFixedThreadPool(n)— пул из n потоковnewCachedThreadPool()— динамический пулnewSingleThreadExecutor()— один потокnewScheduledThreadPool(n)— для планирования
2. Future и Callable
Future позволяет получить результат асинхронного выполнения:
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 42; // результат
}
});
try {
Integer result = future.get(); // получаем результат
System.out.println("Результат: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
3. CountDownLatch
CountDownLatch используется для синхронизации потоков. Один поток ждёт, пока другие потоки завершат работу:
CountDownLatch latch = new CountDownLatch(3); // ждём 3 события
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " начал работу");
// ... работа ...
latch.countDown(); // уменьшаем счётчик
}).start();
}
try {
latch.await(); // блокируемся до countDown() 3 раза
System.out.println("Все потоки завершили работу");
} catch (InterruptedException e) {
e.printStackTrace();
}
4. CyclicBarrier
CyclicBarrier синхронизирует несколько потоков в точке барьера:
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("Все потоки достигли барьера!");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " ждёт");
try {
barrier.await(); // блокируемся
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " продолжает");
}).start();
}
5. Semaphore
Semaphore ограничивает количество потоков, одновременно получающих доступ к ресурсу:
Semaphore semaphore = new Semaphore(2); // максимум 2 потока
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // получаем разрешение
System.out.println(Thread.currentThread().getName() + " работает");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // отпускаем разрешение
}
}).start();
}
6. BlockingQueue
BlockingQueue — потокобезопасная очередь, используется для обмена данными между потоками:
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
// Производитель
new Thread(() -> {
try {
queue.put("Данные 1");
queue.put("Данные 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// Потребитель
new Thread(() -> {
try {
String data = queue.take(); // ждёт, если пусто
System.out.println("Получено: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
7. ConcurrentHashMap
ConcurrentHashMap — потокобезопасная версия HashMap:
Map<String, Integer> map = new ConcurrentHashMap<>();
// Несколько потоков могут одновременно писать
for (int i = 0; i < 10; i++) {
new Thread(() -> {
map.put("key" + i, i);
}).start();
}
// Чтение без синхронизации
map.forEach((k, v) -> System.out.println(k + ": " + v));
8. AtomicInteger и AtomicReference
Атомарные операции без синхронизации:
AtomicInteger counter = new AtomicInteger(0);
for (int i = 0; i < 100; i++) {
new Thread(() -> {
counter.incrementAndGet(); // потокобезопасно
}).start();
}
Thread.sleep(1000);
System.out.println("Значение: " + counter.get()); // 100
9. ReentrantLock
ReentrantLock — явная блокировка, более гибкая чем synchronized:
ReentrantLock lock = new ReentrantLock();
new Thread(() -> {
lock.lock();
try {
System.out.println("Критическая секция");
} finally {
lock.unlock();
}
}).start();
10. Condition
Condition работает с ReentrantLock для передачи сигналов между потоками:
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// Поток, ждущий условия
new Thread(() -> {
lock.lock();
try {
condition.await(); // ждёт сигнала
System.out.println("Сигнал получен");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
// Поток, посылающий сигнал
Thread.sleep(1000);
lock.lock();
try {
condition.signal(); // посылаем сигнал
} finally {
lock.unlock();
}
Когда использовать
- ExecutorService — вместо new Thread()
- CountDownLatch — когда нужно ждать выполнения N событий
- CyclicBarrier — когда потоки должны встретиться в точке
- BlockingQueue — для обмена данными между потоками
- ConcurrentHashMap — вместо synchronized HashMap
- AtomicInteger — для счётчиков
- ReentrantLock — вместо synchronized для сложной логики
Пакет java.util.concurrent — это фундамент для написания надёжного многопоточного кода в Java.