Countdownlatch - это полезный класс инструментов. Используя его, мы можем перехватить один или несколько потоков для выполнения после того, как определенное условие созрело. Его внутреннее содержание обеспечивает счетчик, и начальное значение счетчика должно быть указано при конструировании блокировки, а начальное значение счетчика должно быть больше 0. Кроме того, он также предоставляет метод обратного отсчета для управления значением счетчика. Счетчик будет уменьшен на 1 каждый раз, когда вызывается метод обратного отсчета. Когда значение счетчика уменьшается до 0, это означает, что условия спелые, и все потоки заблокированы, вызывая метод ожидания, будут пробуждены. Это внутренний механизм Countdownlatch. Это выглядит очень просто, это не что иное, как блокировка некоторых потоков и позволяет им выполнять после достижения определенного условия. Тем не менее, Countdownlatch имеет широкий спектр сценариев приложений. Пока у вас есть большой ум и использовать его, вы можете играть в различные трюки. Наиболее распространенным сценарием приложения является включение нескольких потоков выполнять задачу одновременно, а затем подсчитать и суммировать результаты после выполнения всех задач. Следующая рисунка динамически демонстрирует весь процесс блокировки потоков.
На приведенном выше рисунке показано, что 5 потоков блокируются, вызывая метод ожидания, и им необходимо ждать, пока значение счетчика уменьшится до 0, прежде чем продолжить выполнять. Начальное значение счетчика указывается при построении блокировки и впоследствии уменьшается на 1 с каждым вызовом в метод обратного отсчета. Следующий код публикует метод строительства CountDownLatch.
// Constructor public countdownlatch (int count) {if (count <0) бросить новый allosalargumentException ("count <0"); this.sync = new Sync (count); }CountdownLatch имеет только один конструктор параметров, и значение, превышающее 0, должно быть передано как начальное значение счетчика, в противном случае будет сообщена ошибка. Вы можете увидеть это в конструкторе, просто новый объект A Sync и назначить его синхронизации переменной элемента. Как и другие классы инструментов синхронизации, реализация CountDownLatch зависит от AQS, которое является приложением в общем режиме AQS. Countdownlatch реализует внутреннюю класс синхронизацию и использует его для наследственного AQ, так что можно использовать большинство методов, предоставленных AQ. Давайте посмотрим на код синхронизации внутреннего класса.
// синхронизатор частного статического окончательного класса Sync Extends AbstractQueuedSynchronizer {// Constructor Sync (int count) {setState (count); } // Получить текущее состояние синхронизации int getCount () {return getState (); } // Попробуйте получить блокировку // возвращать отрицательное число: указывает, что текущий поток не смог получить // возвращать ноль нулевого значения: указывает на то, что текущий поток был успешно получен, но последующий поток больше не может получить // возвращать положительное число: указывает, что текущий поток был получен успешно, а взысканный поток также может получить успех, защищенный int, 1: -1; } // Попробуйте выпустить блокировку, защищенную логическим пулеанским // Если состояние синхронизации равно 0, if (c == 0) {return false; } // В противном случае уменьшить состояние синхронизации на 1 int nextc = c-1; // Используйте метод CAS для обновления состояния синхронизации if (CompareAndSetState (c, Nextc)) {return nextc == 0; }}}}Вы можете видеть, что конструктор Sync установит значение состояния синхронизации на значение падающего параметра. После этого каждый раз, когда называется метод обратного отсчета, значение синхронного состояния будет уменьшено на 1, что является принципом реализации счетчика. Двумя наиболее часто используемыми методами при использовании класса инструментов CountDownLatch являются метод ожидания и метод обратного отсчета. Вызов метода ожидания будет блокировать текущий поток до тех пор, пока счетчик не станет 0, а вызов метода обратного отсчета не уменьшит значение счетчика на 1, пока он не уменьшится до 0. Давайте посмотрим на то, как называется метод ожидания.
// Причина текущего потока дождаться, пока защелка не уменьшится до 0, или поток не будет прервана публично void wawait () бросает прерывания, чтобы получить {// Приобретение Sync.AcquiResharedIntertable (1);} // Приобретение блокировки в прерываемом режиме (Shareed Mode) Public Final AcquireSharedInterinter Intertable (INT Arg) нарушает прерывание, что -то впоследствии, что -то вводит на то, что он является нарушением, не нарушает, что в первую очередь определяет, что, является, что, то есть, является, что в первую очередь определяет, что, является нарушение, не нарушает. if (think.Erengrupting ()) {бросить новое прерванное перерыв (); } // 1. Попробуйте приобрести Lock if (tryAcquireShared (arg) <0) {// 2. Если приобретение не удается, введите метод DoacquiresharedErenterbully (arg); }}Когда поток вызывает метод ожидания, он фактически вызывает метод AquireSharedEntullable AQS. Этот метод получает блокировку в ответ на перерывы потока. Код для этого метода также опубликован выше. Мы можем видеть, что в методе AcceporeSharedEructable, во -первых, он позвонит в метод TryAcquireShared, чтобы попытаться приобрести блокировку. Мы видим логику метода TryAcquireShared, переписанную в синхронизации. Логика реализации метода очень проста, то есть судить, является ли текущее состояние синхронизации 0. Если это 0, возврат 1 означает, что блокировка может быть получена, в противном случае возврат -1 означает, что блокировка не может быть получена. Если метод TryAcquireShared возвращает 1, поток может продолжать выполняться без ожидания. Если -1 возвращается, то в синхронной очереди будет вызван метод DoAcquiResharedReatmable. Это принцип, который призыв к методу ожидания будет блокировать текущий поток. Давайте посмотрим, как метод обратного отсчета разбудит блокирующую нить.
// Метод уменьшения защелкивания public void countdown () {sync.ReleaseShared (1);} // Операция выпуска (общий режим) Общедоступный окончательный логический релиз (int arg) {// 1. Попробуйте выпустить блокировку if (tryReleaseShared (arg)) {// 2. Если релиз успешно, разбудите другие потоки DoreLeaseShared (); вернуть истину; } вернуть false;}Вы можете видеть, что метод выпуска вызывается в методе обратного отсчета. Этот метод также является методом в AQS. Мы также опубликовали его код. Первое, что в методе выпуска, - это вызвать метод TryReLeaseShared, чтобы попытаться выпустить блокировку. Метод TRYRELEASESHAD - это абстрактный метод в AQS. Его конкретная логика реализации находится в классе Subclass Sync. Мы можем найти этот метод в коде класса Sync, размещенном выше. Если метод TRYRELEASESERED возвращает истину к выпуску и возвращает FALSE, чтобы освободить сбой. Это вернет истину, только если состояние синхронизации составляет ровно 0 после уменьшения 1. В других случаях FALSE будет возвращено. Затем, когда TryReleaseShared возвращает True, метод DoreLeaseSeared будет немедленно вызван, чтобы разбудить все потоки в очереди синхронизации. Это объясняет, почему в последний раз, когда метод обратного отсчета вызывается, чтобы уменьшить счетчик до 0, разбудит все заблокированные потоки. Это основные принципы Countdownlatch. Давайте посмотрим на пример его использования.
Сценарий применения: при игре счастливого арендодателя вы должны ждать, пока все три игрока прибудут, прежде чем вы сможете снять карты.
Public Class Player Extens Thread {Private Static Int Count = 1; Приватный окончательный идентификатор int = count ++; Частная защелка Countdownlatch; Public Player (CountDownLatch Latch) {this.latch = latch; } @Override public void run () {System.out.println ("【Player" + id + "] inting"); latch.countdown (); } public static void main (string [] args) бросает прерывание {countdownlatch latch = new countdownlatch (3); System.out.println («Игра запускается, ожидая, когда игрок войдет ...»); новый игрок (защелка) .start (); новый игрок (защелка) .start (); новый игрок (защелка) .start (); latch.await (); System.out.println («Игроки прибыли, начните иметь дело ...»); }}Результаты операции показывают, что операция сделки должна быть выполнена после того, как все игроки войдут в поле. Мы комментируем 23 строки latch.await () и сравниваем его, чтобы увидеть результаты.
Вы можете видеть, что после комментирования Line Latch.await () не гарантируется, что все игроки начнут разбирать карты только после входа в поле.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.