Бесплатный курс по Java: от основ до продвинутого уровня
Semaphore в Java
Обычно нужен если много потоков одновременно пытаются получить доступ к каким-то ресурсам, а нам нужно, чтобы к ним одновременно получала доступ только часть из потоков, при этом, оставшиеся потоки стояли в очереди и если какой-то поток оставил ресурс, нужно, чтобы сразу занимал его место один из стоящих в очереди.
Пример программы:
import java.io.*;
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore resources = new Semaphore(3); // три разрешения
// То есть одновременно могут выполняться только
// три потока, все остальные стоят в очереди пока
// одно из трех мест не освободится.
for (int i = 1; i < 10; i++) {
SomeThread t = new SomeThread();
t.setName("Thread " + i);
t.resources = resources;
t.start();
}
}
}
class SomeThread extends Thread {
Semaphore resources;
@Override
public void run() {
try {
// Поток занимает одно из трех разрешений
resources.acquire();
System.out.println(
Thread.currentThread().getName()
+ " entered the resource"
);
Thread.sleep(1000);
System.out.println(
Thread.currentThread().getName()
+ " left the resource"
);
resources.release(); // Поток покидает одно
// из трех разрешений, после этого оставленное
// разрешение сразу занимает другой поток,
// стоявший в очереди на занятие разрешения,
// поскольку не мог занять разрешение, так как
// все три были заняты другими потоками.
} catch (InterruptedException e) {}
}
}
Вывод:
Из консоли видно, что одновременно выполняются только три потока.
Программа выполняется в следующей последовательности:
Видим, что сначала выполняются только 1,2,3 поток.
Потом 1,2 поток завершают свое выполнение. И на их место стразу становятся 4,6 потоки, которые стояли в очереди.
Далее завершает свою работу 3 поток, и на его место сразу становиться 5 поток.
То есть, очевидно, что параллельно друг другу всё время работают только три потока.
ReentrantLock в Java: мощная альтернатива synchronized с гибкой блокировкой любых участков кода. Примеры, отличия и преимущества для многопоточности.
Time to read: 11
Ожидание завершения потоков с помощью CountDownLatch
CountDownLatch в Java: механизм ожидания завершения потоков. Как использовать await() и countDown() для синхронизации. Практический пример и разбор работы.
Time to read: 10
CyclicBarrier в Java
Изучите CyclicBarrier в Java: как синхронизировать потоки и запускать дополнительное действие после завершения заданного количества потоков. Пример кода и объяснение работы.