Используйте wate () и notify () для достижения межпоточного сотрудничества
1. wate () и notify ()/notifyall ()
Когда вызываются Sleep () и helive (), замок не выпускается, а вызов wait () отпустит блокировку. Таким образом, другая задача (поток) может получить блокировку текущего объекта, тем самым введя его синхронизированный метод. Вы можете возобновить выполнение из wait () через notify ()/notifyall () или время истекает.
Wat (), notify () и notifyall () можно вызвать только в методе управления синхронизацией или блоком синхронизации. Если эти методы вызываются в асинхронном методе, исключение нелегаламонного статового процесса будет брошено во время выполнения.
2. Моделируйте пробуждение нескольких потоков одним потоком
Имитировать сотрудничество между потоками. У класса игры есть 2 метода синхронизации Prepare () и Go (). Запуск флага используется для определения того, нужен ли текущий поток ждать (). Экземпляр класса игры запускает все экземпляры класса Athele в первую очередь и введите состояние wait (). Через некоторое время измените флаг бит и уведомляет () все резьбы Athele в состоянии ожидания.
Game.java
Пакет параллеризации; импорт java.util.collection; import java.util.collections; импорт java.util.hashset; import java.util.iterator; import java.util.set; класс спортсмен реализует беглый {частный финальный ID; частная игра; Public Athlete (INT ID, Game Game) {this.id = id; this.game = game; } public boolean equals (Object o) {if (! (o экземпляр спортсмена)) вернуть false; Спортсмен спортсмен = (спортсмен) O; return id == Athlete.id; } public String toString () {return "спортсмен <" + id + ">"; } public int hashcode () {return new Integer (id) .hashcode (); } public void run () {try {game.prepare (this); } catch (прерывание Exception e) {System.out.println (this + "уйти в игру"); } / Частный логический старт = false; public void AddPlayer (Athlete One) {Player.Add (One); } public void lementPlayer (Athlete One) {player.remove (one); } public Collection <Athlete> getPlayers () {return Collections.UnmodifiableSet (игроки); } public void Prepare (спортсмен -спортсмен) Throws TreamptenException {System.out.println (спортсмен + "Готов!"); синхронизированный (это) {while (! start) wat (); if (start) system.out.println (спортсмен + "Go!"); }} public synchronized void go () {notifyall (); } public void Ready () {iterator <Athlete> iter = getPlayers (). iterator (); while (iter.hasnext ()) новый поток (iter.next ()). start (); } public void run () {start = false; System.out.println ("Готово ..."); System.out.println ("Готово ..."); System.out.println ("Готово ..."); готовый(); start = true; System.out.println ("Go!"); идти(); } public static void main (String [] args) {Game Game = new Game (); для (int i = 0; i <10; i ++) game.addplayer (новый спортсмен (i, game)); новая ветка (игра) .start (); }} результат:
Готов ... готов ... готов ... спортсмен <0> Готовы! Спортсмен <1> Готовы! Спортсмен <2> Готовы! Спортсмен <3> Готовы! Спортсмен <4> Готовы! Спортсмен <5> Готовы! Спортсмен <6> Готовы! Атлет <7> Готовы! Спортсмен <8> Готов! Иди! Спортсмен <3> Иди! Спортсмен <2> Иди! Спортсмен <1> Иди! Спортсмен <0> Иди!
3. Имитация процесса оживленного ожидания
Примером класса MyObject является наблюдатель. Когда произойдет событие наблюдения, оно уведомит экземпляр класса монитора (как это следует изменить). Экземпляр этого класса монитора постоянно проверяет, изменяется ли бит флага, ожидая.
Занят waiting.java
Import java.util.concurrent.timeUnit; класс myobject реализует runnable {private Monitor; public myobject (монитор монитора) {this.monitor = monitor; } public void run () {try {timeUnit.seconds.sleep (3); System.out.println («Я иду.»); monitor.gotmessage (); } catch (прерванное искусство e) {e.printstacktrace (); }}} монитор класса реализует runnable {private volatile Boolean go = false; public void gotMessage () бросает прерванную экспрессию {go = true; } public void stimal () {while (go == false); System.out.println («Он ушел»); } public void run () {watch (); }} public class rablewaiting {public static void main (string [] args) {monitor monitor = new Monitor (); MyObject o = новый myObject (монитор); новый поток (o) .start (); новый поток (монитор) .start (); }} результат:
Я иду. Он ушел.
4. Используйте wate () и notify (), чтобы переписать приведенный выше пример
В следующем примере заменяет механизм оживленного ожидания через wait (). При получении сообщения уведомления, уведомить текущий поток класса монитора.
Подожди. Ява
Package condurance.wait; import java.util.concurrent.timeUnit; класс MyObject реализует Runnable {Private Monitor Monitor; public myobject (монитор монитора) {this.monitor = monitor; } Начать поток регулярно
Вот два способа запустить поток после указанного времени. Во -первых, он реализован через java.util.concurrent.delayqueue; Во -вторых, он реализован через java.util.concurrent.scheduledthreadpoolexecutor.
1. java.util.concurrent.delayqueue
Классовая задержка - это неограниченная очередь блокировки, из которой элементы могут быть извлечены только при истечении срока задержки. Он принимает случаи, которые реализуют задерживаемый интерфейс в качестве элементов.
<< Интерфейс >> задержка. Java
Package java.util.concurrent; Import java.util.*; Общедоступный интерфейс задержанный Extends сопоставимо <doseed> {long getDelay (UNIT TimeUnit);}getDelay () возвращает оставшееся время задержки, связанное с этим объектом, выраженное в данных единицах времени. Реализация этого интерфейса должна определить метод сравнения, который обеспечивает согласованное сортирование с методом GetDelay этого интерфейса.
Голова очереди задержки - это задержка элемента с самым длинным временем хранения после истечения срока задержки. Срок годности происходит, когда метод getDelay (TimeUnit.nanoseconds) элемента возвращает значение меньше или равное 0.
2. Дизайн очереди с характеристиками задержки времени
Класс DeploadEdTasker поддерживает очередь DolectQueue <SoteredTask>, где DopendTask реализует задержку интерфейса и определяется внутренним классом. Как внешние классы, так и внутренние классы реализуют запускаемый интерфейс. Для внешних классов метод выполнения выполняет задачи в очереди в последовательности в соответствии с определенным временем, и эти задачи являются экземплярами внутренних классов. Метод запуска внутренних классов определяет конкретную логику каждого потока.
Суть этого дизайна состоит в том, чтобы определить список задач потока с характеристиками времени, и список может иметь любую длину. Укажите время запуска каждый раз, когда вы добавляете задачу.
SoydeDtasker.java
Пакет com.zj.timedtask; импорт static java.util.concurrent.timeunit.seconds; импорт static java.util.concurrent.timeunit.nanoseconds; импорт java.util.collection; import java.util.collections; импорт java.utilections; импорт. java.util.concurrent.delayed; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.timeUnit; public class soydetsker реализуется {deslayqueue <sostedTask> Queue; public void AddTask (DoyedTask e) {queue.put (e); } public void removeTask () {queue.poll (); } public Collection <SoteredTask> getAlltasks () {return Collections.UnModifiaBlecollection (queue); } public int getTaskquantity () {return queue.size (); } public void run () {while (! queue.isempty ()) try {queue.take (). run (); } catch (прерывание Exception e) {System.out.println ("прерван"); } System.out.println ("Закончена DoyedTask"); } public Static Class DoyedTask реализует отсроченные, запускаемые {private Static int counter = 0; Приватный окончательный идентификатор int = counter ++; Частный финал Int Delta; частный последний длинный триггер; public doyedTask (int dolesInseconds) {delta = dolesInseconds; trigger = System.nanotime () + nanoseconds.convert (delta, секунд); } public long getDelay (UNIT UNIT) {return Unit.convert (Trigger - System.nanotime (), Nanoseconds); } public int CompareTo (отсроченный arg) {doyedTask that = (doyedTask) arg; if (Trigger <that.trigger) return -1; if (Trigger> that.trigger) возвращает 1; возврат 0; } public void run () {// запустить все, что вы хотите сделать System.out.println (this); } public String toString () {return "[" + delta + "s]" + "задача" + id; }} public static void main (string [] args) {случайный rand = new Random (); Executorservice exec = executors.newcachedthreadpool (); DoyedTasker Tasker = new DoledEdTasker (); для (int i = 0; i <10; i ++) tasker.addtask (new DoledEdTask (rand.nextint (5))); exec.execute (tasker); exec.shutdown (); }} результат:
[0s] Задача 1 [0s] Задача 2 [0s] Задача 3 [1S] Задача 6 [2S] Задача 5 [3S] Задача 8 [4S] Задача 0 [4S] Задача 4 [4S] Задача 7 [4S] Задача 9FINEDEDELAYEDTASK
3. java.util.concurrent.scheduledThreadPoolexeCutor
Этот класс может быть запланирован для выполнения задач (потоков) после данной задержки или регулярно выполнять задачи (повторить). В конструкторе вам нужно знать размер пула потоков. Основным методом:
[1] График
Общественный запланированный расписание <?>
Создает и выполняет единовременную работу, включенную после данной задержки.
Обозначено:
- Расписание в интерфейсе warededexecutorservice;
Параметр:
-ПОММАНД - задача, которая должна быть выполнена;
-Дел - время задержать исполнение с этого момента;
-unit - временная единица параметров задержки;
возвращаться:
- Указывает запланированную мощность, которая приостанавливает задачу, и ее метод get () вернет нуль после завершения.
[2] PradeuleAtFixEdrate
public glededfuture <?> seduleatfixedrate (
Запустить команду, Long InitialLay, длительный период, Unit Unit)
Создать и выполнить периодическую операцию, которая сначала включена после заданной начальной задержки, причем последующие операции имеют определенный период; То есть он начнется после InitialDelay, затем после периода initialLay +, затем после периода initialLay + 2 * и так далее. Если какое -либо выполнение задачи столкнется с исключением, последующее выполнение будет отменено. В противном случае задача может быть прекращена только путем выполнения метода отмены или завершения программы. Если какое -либо из выполнения этой задачи займет больше времени, чем его цикл, последующее выполнение будет отложено, но не одновременно.
Обозначено:
- PradeuleAtFixEdrate в интерфейсе warededExecutorservice;
Параметр:
-ПОММАНД - задача, которая должна быть выполнена;
-initiaLdelay - время задержки для первого исполнения;
-Ппериод - период между непрерывными казни;
-Уньян - временная единица параметров initialdelay и периода;
возвращаться:
- Указывает, что запланированная переходная задача выполнена, и его метод get () вызовет исключение после его отмены.
4. Разработчивые исполнители потока с характеристиками задержки времени
Class MadeleTasked ассоциирует запланированную сайте, в котором можно указать размер пула потоков. Знайте поток и время задержки с помощью метода расписания и закройте пул потоков с помощью метода выключения. Логика конкретных задач (потоков) обладает определенной гибкостью (по сравнению с предыдущим дизайном, предыдущая конструкция должна заранее определить логику потока, но конкретная логическая конструкция потока может быть изменена путем наследования или украшения).
Wareduletasker.java
пакет com.zj.timedtask; import java.util.concurrent.schedudThreadPoolexeCutor; import java.util.concurrent.timeUnit; открытый класс PredicueSker {private int corepoolsize = 10; GraduledThreadPoolexeCutor Scheduler; public swarduleTasker () {pradeler = new SeduledThreadPoolexeCutor (corePoolsize); } public sweduleTasker (int Количество) {corePoolsize = количество; Scheduler = New PredicleDThreadPoolexeCutor (corePoolsize); } public void -график (runnable event, long Deloge) {scheduler.schedule (событие, задержка, временные районы. seconds); } public void shutdown () {scheduler.shutdown (); } public static void main (string [] args) {preduleTasker tasker = new preduleTasker (); tasker.schedule (new Runnable () {public void run () {System.out.println ("[1S] Task 1");}}, 1); tasker.schedule (new Runnable () {public void run () {System.out.println ("[2S] Task 2");}}, 2); tasker.schedule (new Runnable () {public void run () {System.out.println ("[4S] Task 3");}}, 4); tasker.schedule (new Runnable () {public void run () {public void run () {system.out.println ("[10S] задача 4");}}, 10); tasker.shutdown (); }} результат:
[1S] Задача 1 [2S] Задача 2 [4S] Задача 3 [10S] Задача 4 public void run () {try {timeUnit.seconds.sleep (3); System.out.println («Я иду.»); monitor.gotmessage (); } catch (прерванное искусство e) {e.printstacktrace (); }}} Класс -монитор реализует runnable {private volatile boolean go = false; public synchrinized void gotmessage () бросает прерывания, {go = true; notify (); } public Synchronized void watch () Throws treamptEdException {while (go == false) wat (); System.out.println («Он ушел»); } public void run () {try {sime (); } catch (прерванное искусство e) {e.printstacktrace (); } / MyObject o = новый myObject (монитор); новый поток (o) .start (); новый поток (монитор) .start (); }} результат:
Я иду. Он ушел.