CountDownLatch и Semaphore
В общем то,достаточно сжатая информация об удобных вещах в пакете java.util.concurrent,
а точнее о паре вещей оттуда.
CountDownLatch
CountDownLatch класс защелка,позволяет задержать поток(и) до тех пор,пока не выполнится определенное условие,а именно пока счетчик заданный в конструкторе не дойдет до 0.
Вообще создание объекта происходит следующим образом
CountDownLatch latch = new CountDownLatch(3);//по количеству потоков которых мы будем ждать
И 2 основных метода
countDown и await.
Метод await заставляет текущий поток ожидать,пока счетчик защелки не станет равен 0.
Метод countDown декрементит счетчик заданный в конструкторе и как только он дойдет до 0,потоки продолжат выполнение.
Вот пример со скачками(пример не мой,я только напихал больше комментариев по коду,ну и сократил лишнее)
Метод await заставляет текущий поток ожидать,пока счетчик защелки не станет равен 0.
Метод countDown декрементит счетчик заданный в конструкторе и как только он дойдет до 0,потоки продолжат выполнение.
Вот пример со скачками(пример не мой,я только напихал больше комментариев по коду,ну и сократил лишнее)
class Race { private Random rand = new Random(); private int distance = 50; private Listhorses = Arrays.asList("Vanek","Robert","Polson","Rak"); public void run() throws InterruptedException { System.out.println("And the horses are stepping up to the gate..."); final CountDownLatch start = new CountDownLatch(1);//защелка для одновременного старта для всех коней,1-тк защелка для основного потока выполнения start.await(); final CountDownLatch finish = new CountDownLatch(horses.size());//защелка для финиша, а здесь по количеству лошадей final List places = Collections.synchronizedList(new ArrayList<>()); horses.forEach(horse -> new Thread(() -> { try { System.out.println(horse + " stepping up to the gate..."); start.await(); // Блокируем поток,чтобы не было не одного фальстарта у наших коней int traveled = 0;//пройденный путь для коня while (traveled < distance) { // каждые 0-2 секунды лошадь проходит дистанцию 0-14 пунктов Thread.sleep(rand.nextInt(3) * 1000); traveled += rand.nextInt(15); System.out.println(horse + " advanced to " + traveled + "!"); } finish.countDown();//уменьшение счетчика защелки,тк мы будем ждать именно этого момента в самой программе и когда последний конь финиширует исполнение завершится System.out.println(horse + " crossed the finish!"); places.add(horse); } catch (InterruptedException intEx) { System.out.println("ABORTING RACE!!!"); intEx.printStackTrace(); } }).start()); System.out.println("And... they're off!"); start.countDown();//снимаем нашу защелку для старта finish.await();//ожидаем финиша наших скакунов System.out.println("And we have our winners!"); System.out.println(places.get(0) + " took the gold..."); System.out.println(places.get(1) + " got the silver..."); System.out.println("and " + places.get(2) + " took home the bronze."); } public static void main(String[] args) throws InterruptedException { new Race().run(); } }
Вот как то так.
Теперь про класс Semaphore.
Он, как видно из названия,служит для ограничения количества потоков использующих определенный ресурс.Создается объект как то так
Semaphore available = new Semaphore(3);//по количеству потоков которые будут активны
И 2 основных метода acquire() и release().
acquire()-Уменьшает счетчик доступных потоков(который мы задали в конструкторе) на 1.
release()-Соответственно освобождает его и увеличивает счетчик.
Небольшой пример
public static void main(String[] args) { Runnable limitedCall = new Runnable() { final Random rand = new Random(); final Semaphore available = new Semaphore(3); int count = 0; public void run() { int time = rand.nextInt(15); int num = count++; try { available.acquire();//задействуем поток System.out.println("Executing " + "long-running action for " +time + " seconds... #" + num); Thread.sleep(time * 1000); System.out.println("Done with #" + num + "!"); available.release();//после его работы освобождаем } catch (InterruptedException intEx) { intEx.printStackTrace(); } } }; for (int i=0; i<10 data-blogger-escaped-i="" data-blogger-escaped-limitedcall="" data-blogger-escaped-new="" data-blogger-escaped-pre="" data-blogger-escaped-start="" data-blogger-escaped-thread="">Создаем 10 потоков(можно убедиться выполнив команду jstack),однако только 3 из них активны.Как только один их потоков освобождает семафор,другой занимает его место.
Вот и все.