русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Методы wait() и notifyAII()


Дата добавления: 2015-06-12; просмотров: 838; Нарушение авторских прав


Метод wait() ожидает изменения некоторого условия, неподконтрольного для текущего метода. Довольно часто это условие изменяется в результате выполнения другой задачи. Активное ожидание, то есть проверка условия в цикле, не­желательно из-за неэффективного расходования вычислительных ресурсов. Таким образом, метод wait() обеспечивает механизм синхронизации действий между задачами.

Важно понять, что метод sleep() не освобождает объект блокировки. С другой стороны, метод wait() снимает блокировку с объекта, тем самым позволяя остальным потокам вызывать другие синхронизированные методы объекта во время выполнения wait(). Это очень важно, потому что обычно именно «другие» методы приводят к изменению условия и активизации приостановленной задачи.

Существует две формы метода wait(). У первой формы аргумент имеет такой же смысл, как и аргумент метода sleep(): это продолжительность интервала в миллисекундах, на который приостанавливается выполнение потока. Разница между методами состоит в следующем:

· При выполнении метода wait() блокируемый объект освобождается.

· Выйти из состояния ожидания, установленного wait(), можно двумя способами: с помощью уведомления notify() или notifyAll() либо по истечении срока ожидания.

Вторая, более распространенная форма вызывается без аргументов. Эта версия метода wait() заставит поток простаивать, пока не придет уведомление notify() или notifyAll().

Пожалуй, самое интересное в методах wait(), notify() и notifyAll() — их принадлежность к общему классу Object, а не к классу потоков Thread. Хотя это и кажется немного нелогичным — размещение чего-то, относящегося исключительно к механизму потоков, в общем базовом классе — на самом деле это решение совершенно оправдано, поскольку означенные методы манипулируют блокировками, которые являются частью любого объекта. В результате ожидание (wait()) может использоваться в любом синхронизированном методе, независимо от того, наследует ли класс от Thread или реализует Runnable. Вообще говоря, единственное место, где допустимо вызывать метод wait(), — это синхронизированный метод или блок (метод sleep() можно вызывать в любом месте, так как он не манипулирует блокировкой). Если вызвать метод wait() или notify() в обычном методе, программа скомпилируется, однако при ее выполнении возникнет исключение IllegalMonitorStateException с несколько туманным сообщением «текущий поток не является владельцем» («current thread not owner»). Это сообщение означает, что поток, востребовавший методы wait(), notify() или notifyAll(), должен быть «хозяином» блокируемого объекта (овладеть объектом блокировки) перед вызовом любого из данных методов.



Вы можете «попросить» объект провести операции с помощью его собственного объекта блокировки. Для этого необходимо сначала захватить блокировку для данного объекта. Например, если вы хотите вызвать notifyAll() для объекта х, то должны сделать это в синхронизируемом блоке, устанавливающем блокировку для х:

synchronized(x) { х.notifyAll();}

Рассмотрим простой пример. В программе WaxOMatic.java задействованы два процесса: один наносит восковую пасту на автомашину (Саr), а другой полирует ее. Задача полировки не может приступить к работе до того, как задача нанесения пасты завершит свою операцию, а задача нанесения пасты должна ждать завершения полировки, чтобы наложить следующий слой пасты. Оба класса, WaxOn и WaxOff, используют объект Саr, который приостанавливает и возобновляет задачи в ожидании изменения условия:

//: concurrency/waxomatic/WaxOMatic.java

// Простейшее взаимодействие задач.

package concurrency.waxomatic;

import java.util.concurrent.*;

import static net.mindview.util.Print.*;

 

class Car {

private boolean waxOn = false;

public synchronized void waxed() {

waxOn = true; // Готово к обработке

notifyAll();

}

public synchronized void buffed() {

waxOn = false; // Готово к нанесению очередного слоя

notifyAll();

}

public synchronized void waitForWaxing()

throws InterruptedException {

while(waxOn == false)

wait();

}

public synchronized void waitForBuffing()

throws InterruptedException {

while(waxOn == true)

wait();

}

}

 

class WaxOn implements Runnable {

private Car car;

public WaxOn(Car c) { car = c; }

public void run() {

try {

while(!Thread.interrupted()) {

printnb("Wax On! ");

TimeUnit.MILLISECONDS.sleep(200);

car.waxed();

car.waitForBuffing();

}

} catch(InterruptedException e) {

print("Exiting via interrupt");

}

print("Ending Wax On task");

}

}

 

class WaxOff implements Runnable {

private Car car;

public WaxOff(Car c) { car = c; }

public void run() {

try {

while(!Thread.interrupted()) {

car.waitForWaxing();

printnb("Wax Off! ");

TimeUnit.MILLISECONDS.sleep(200);

car.buffed();

}

} catch(InterruptedException e) {

print("Exiting via interrupt");

}

print("Ending Wax Off task");

}

}

 

public class WaxOMatic {

public static void main(String[] args) throws Exception {

Car car = new Car();

ExecutorService exec = Executors.newCachedThreadPool();

exec.execute(new WaxOff(car));

exec.execute(new WaxOn(car));

TimeUnit.SECONDS.sleep(5); // Небольшая задержка...

exec.shutdownNow(); // Прерывание всех задач

}

}

<spoiler text="Output:"> (95% match)

Wax On! Wax Off! Wax On! Wax Off! Wax On! Wax Off! Wax On! Wax Off! Wax On!

Wax Off! Wax On! Wax Off! Wax On! Wax Off! Wax On! Wax Off! Wax On! Wax Off!

Wax On! Wax Off! Wax On! Wax Off! Wax On! Wax Off! Wax On! Exiting via interrupt

Ending Wax On task

Exiting via interrupt

Ending Wax Off task

</spoiler> Класс Саr содержит одну логическую переменную waxOn, которая описывает текущее состояние процесса полировки. Метод waitForWaxing() проверяет флаг waxOn, и, если он равен false, вызывающая задача приостанавливается вызовом wait(). Очень важно, что это происходит в синхронизированном методе. При вызове wait() поток приостанавливается, а блокировка снимается. Последнее принципиально, потому что для безопасного изменения состояния объекта (например, для присваивания waxOn значения true, без чего приостановленная задача не сможет продолжить работу) блокировка должна быть доступна для другой задачи. В нашем примере при вызове другой задачей метода waxed(), указывающего, что пришло время что-то сделать, для задания истинного значения waxOn необходимо установить блокировку. Затем waxed() вызывает notifyAll(); задача, приостановленная вызовом wait(), активизируется. Для этого нужно сначала заново получить блокировку, освобожденную при входе в wait(). Задача не активизируется, пока блокировка не станет доступной.



<== предыдущая лекция | следующая лекция ==>
Static void | Использование каналов для ввода/вывода между потоками


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.117 сек.