Пакет java.util.concurrent
предоставляет несколько классов и конструкций, которые обеспечивают более детальный контроль над синхронизацией и предназначены для обработки расширенных сценариев параллелизма. Вот некоторые ключевые классы и конструкции, которые могут быть полезны:
Lock
Интерфейс: Интерфейсjava.util.concurrent.locks.Lock
обеспечивает более гибкую альтернативу внутренней блокировке (synchronized
блоки/методы). Он обеспечивает явную блокировку и разблокировку, поддерживает различные стратегии блокировки и предоставляет дополнительные функции, такие как справедливость, прерываемое получение блокировки и попытки блокировки по времени. Наиболее часто используемая реализация —ReentrantLock
.ReadWriteLock
Интерфейс: Интерфейсjava.util.concurrent.locks.ReadWriteLock
позволяет различать блокировки чтения и записи. Это позволяет нескольким потокам одновременно читать общий ресурс, обеспечивая при этом монопольный доступ для записи. КлассReentrantReadWriteLock
является стандартной реализацией этого интерфейса.- Класс
Semaphore
: Классjava.util.concurrent.Semaphore
представляет собой примитив синхронизации, который позволяет контролировать доступ к ограниченному числу ресурсов. Он предоставляет определенное количество разрешений, которые могут быть получены и освобождены потоками. Семафоры полезны в сценариях, где вы хотите ограничить одновременный доступ к определенному количеству ресурсов. - Класс
CountDownLatch
: Классjava.util.concurrent.CountDownLatch
представляет собой средство синхронизации, которое позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках. Он инициализируется счетчиком, и каждый вызовcountDown()
уменьшает счетчик. Потоки могут ждать, пока счетчик достигнет нуля, используя методawait()
. - Класс
CyclicBarrier
: Классjava.util.concurrent.CyclicBarrier
— это еще одно средство синхронизации, которое позволяет группе потоков ожидать у барьера, пока все потоки не достигнут его. После прибытия всех потоков выполняется указанное барьерное действие.CyclicBarrier
может быть полезен в сценариях, где вы хотите синхронизировать ход выполнения нескольких потоков в определенные моменты. Executor
Платформа: Платформаjava.util.concurrent.Executor
обеспечивает абстракцию более высокого уровня для управления и асинхронного выполнения задач в пуле потоков. Он предлагает различные реализации, такие какThreadPoolExecutor
,ScheduledThreadPoolExecutor
, а также служебные классы, такие какExecutors
, для упрощения отправки и выполнения задач.- Класс
CompletableFuture
: Классjava.util.concurrent.CompletableFuture
предоставляет мощный способ обработки асинхронных вычислений и их компоновки неблокирующим способом. Он поддерживает связывание и объединение нескольких асинхронных операций, обработку исключений и выполнение обратных вызовов после завершения вычислений.
Теперь приведите пример для каждого из них
Интерфейс блокировки. В этом примере ReentrantLock
используется для синхронизации доступа к критическому разделу кода (метод criticalSection()
). Блокировка устанавливается с помощью lock.lock()
и снимается с помощью lock.unlock()
.
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class SharedResource { private Lock lock = new ReentrantLock(); public void criticalSection() { lock.lock(); try { // Critical section code } finally { lock.unlock(); } } }
ReadWriteLock
Интерфейс (с использованием ReentrantReadWriteLock
):
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; class SharedResource { private ReadWriteLock lock = new ReentrantReadWriteLock(); private int value; public int readValue() { lock.readLock().lock(); try { return value; } finally { lock.readLock().unlock(); } } public void writeValue(int newValue) { lock.writeLock().lock(); try { value = newValue; } finally { lock.writeLock().unlock(); } } }
В этом примере ReentrantReadWriteLock
используется для разрешения одновременного чтения (readValue()
) и эксклюзивной записи (writeValue()
) к общему ресурсу (value
).
Semaphore
Класс:
import java.util.concurrent.Semaphore; class ResourcePool { private Semaphore semaphore; public ResourcePool(int maxResources) { semaphore = new Semaphore(maxResources); } public void useResource() throws InterruptedException { semaphore.acquire(); try { // Use the resource } finally { semaphore.release(); } } }
В этом примере Semaphore
используется для управления доступом к ограниченному количеству ресурсов (maxResources
). Метод useResource()
получает разрешение от семафора перед использованием ресурса и после этого освобождает его.
CountDownLatch
Класс:
import java.util.concurrent.CountDownLatch; class Worker implements Runnable { private CountDownLatch latch; public Worker(CountDownLatch latch) { this.latch = latch; } public void run() { // Perform work latch.countDown(); // Signal completion } } class Main { public static void main(String[] args) throws InterruptedException { int workerCount = 3; CountDownLatch latch = new CountDownLatch(workerCount); for (int i = 0; i < workerCount; i++) { Worker worker = new Worker(latch); Thread thread = new Thread(worker); thread.start(); } latch.await(); // Wait for all workers to complete System.out.println("All workers have completed."); } }
В этом примере CountDownLatch
используется для координации нескольких рабочих потоков (класс Worker
). Основной поток ожидает завершения всех рабочих процессов, вызывая latch.await()
, а затем приступает к печати сообщения о завершении.
CyclicBarrier
Класс:
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; class Worker implements Runnable { private CyclicBarrier barrier; public Worker(CyclicBarrier barrier) { this.barrier = barrier; } public void run() { try { // Perform partial work barrier.await(); // Wait for other workers // Perform remaining work after synchronization } catch (InterruptedException | BrokenBarrierException e) { // Handle exceptions } } } class Main { public static void main(String[] args) { int workerCount = 3; CyclicBarrier barrier = new CyclicBarrier(workerCount, () -> { System.out.println("All workers have reached the barrier."); }); for (int i = 0; i < workerCount; i++) { Worker worker = new Worker(barrier); Thread thread = new Thread(worker); thread.start(); } } }
В этом примере CyclicBarrier
используется для синхронизации нескольких рабочих потоков (класс Worker
). Каждый рабочий выполняет частичную работу, а затем ждет у шлагбаума, используя barrier.await()
. Как только все работники достигают барьера, выполняется действие барьера и печатается сообщение.
Executor Framework (с использованием ThreadPoolExecutor):
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class Task implements Runnable { private int taskId; public Task(int taskId) { this.taskId = taskId; } public void run() { System.out.println("Task " + taskId + " is executing."); // Perform the task logic } } class Main { public static void main(String[] args) { int threadPoolSize = 3; ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize); for (int i = 0; i < 5; i++) { Task task = new Task(i); executor.execute(task); } executor.shutdown(); } }
В этом примере ThreadPoolExecutor
из платформы Executor используется для управления пулом потоков фиксированного размера. Задачи, представленные классом Task
, передаются исполнителю с помощью executor.execute(task)
и выполняются одновременно доступными потоками в пуле.
CompletableFuture Класс :
import java.util.concurrent.CompletableFuture; class Main { public static void main(String[] args) { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // Perform an asynchronous computation return "Result"; }); future.thenAccept(result -> { // Process the result when the computation completes System.out.println("Result: " + result); }); future.exceptionally(ex -> { // Handle exceptions that occurred during the computation System.out.println("Exception: " + ex.getMessage()); return null; }); } }
В этом примере CompletableFuture
создается с использованием метода supplyAsync
, который представляет собой асинхронное вычисление. Метод thenAccept
определяет обратный вызов, который вызывается с результатом вычисления после его завершения. Метод exceptionally
позволяет обрабатывать любые исключения, возникшие во время вычислений.
Эти примеры дают представление об использовании платформы Executor и класса CompletableFuture. Они предлагают абстракции более высокого уровня для управления параллельными задачами и обработки асинхронных вычислений более рациональным и эффективным способом.
Эти примеры иллюстрируют базовое использование каждой утилиты параллелизма. Вы можете модифицировать и адаптировать их, чтобы они соответствовали более сложным сценариям и требованиям ваших собственных приложений.