Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

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

synchronized(x) { х notifyAllО;

}

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

//: 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 waitForWaxingO throws InterruptedException { while(waxOn == false) waitO;

}

public synchronized void waitForBuffingO throws InterruptedException {

while(waxOn == true) продолжение &

waitO;

}

}

class WaxOn implements Runnable { private Car car;

public WaxOn(Car c) { car = c; } public void run { try {

while( IThread interruptedO) { printnbC'Wax On! "); Ti mellni t. MILLISECONDS. si eep( 200); car.waxedO; car.waitForBuffingO;

}

} catchdnterruptedException e) {

printC'Exiting via interrupt");

}

print("Ending Wax On task");

}

}

class WaxOff implements Runnable { private Car car;

public WaxOff(Car c) { car = c; } public void runO { try {

while(IThread.interruptedO) { car.waitForWaxingO; printnbC'Wax Off! "); Ti mellni t. MILLI SECONDS. s 1 eep (200); car.buffedO;

}

} catchdnterruptedException e) {

printC'Exiting via interrupt");

}

printC'Ending Wax Off task");

public class WaxOMatic {

public static void main(String[] args) throws Exception { Car car = new CarO;

ExecutorService exec = Executors.newCachedThreadPoolО;

exec.execute(new WaxOff(car));

exec.execute(new WaxOn(car));

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

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

}

} /* Output:

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 *///:-

Класс Саг содержит одну логическую переменную waxOn, которая описывает текущее состояние процесса полировки.

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

Использование каналов для ввода/вывода между потоками

Часто бывает полезно организовать взаимодействие потоков посредством механизмов ввода/вывода. Библиотеки потоков могут предоставлять поддержку ввода/вывода между потоками в форме каналов (pipes). Последние представлены в стандартной библиотеке ввода/вывода Java классами PipedWriter (позволяет потоку записывать в канал) и PipedReader (предоставляет возможность другому потоку считывать из того же канала).

Простой пример взаимодействия двух потоков через канал:

//• concurrency/PipedlO.java

// Использование каналов для ввода/вывода между потоками

import java.util.concurrent.*;

import java.io.*;

import java.util.*;

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

class Sender implements Runnable {

private Random rand = new Random(47); private PipedWriter out = new PipedWriterO; pubTic PipedWriter getPipedWriterO { return out, } public void run { try {

while(true)

for(char с = 'А'; с <= 'z'; С++) { out write(c);

TimeUnit.MILLISECONDS.sleep(rand.nextlnt(500));

}

} catch(IOException e) {

print(e + " Sender write exception"); } catch(InterruptedException e) {

print(e + " Sender sleep interrupted");

}

}

class Receiver implements Runnable { private PipedReader in;

public Receiver(Sender sender) throws IOException {

in = new PipedReader(sender.getPipedWriterO).

}

public void run { try {

while(true) {

// Блокируется до появления следующего символа, printnb("Read- " + (char)in.readO + ");

}

} catch(IOException e) {

print(e + " Receiver read exception");

public class PipedIO {

public static void main(String[] args) throws Exception { Sender sender = new SenderO; Receiver receiver = new Receiver(sender); ExecutorService exec = Executors.newCachedThreadPool0; exec.execute(sender); exec.execute(receiver); TimeUnit.SECONDS.sleep(4); exec.shutdownNowO;

}

} /* Output:

Read: A, Read: B. Read: C. Read: D, Read- E, Read. F, Read: G, Read: H, Read: I. Read: J. Read: K, Read: L, Read: M, java.lang.InterruptedException: sleep interrupted Sender sleep interrupted

Поделиться:
Популярные книги

Возвращение

Кораблев Родион
5. Другая сторона
Фантастика:
боевая фантастика
6.23
рейтинг книги
Возвращение

Вперед в прошлое 9

Ратманов Денис
9. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 9

Кукловод

Майерс Александр
4. Династия
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кукловод

Господин Хладов

Шелег Дмитрий Витальевич
4. Кровь и лёд
Фантастика:
аниме
5.00
рейтинг книги
Господин Хладов

Мужчина моей судьбы

Ардова Алиса
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Мужчина моей судьбы

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Последний Паладин. Том 6

Саваровский Роман
6. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 6

Первый среди равных. Книга VIII

Бор Жорж
8. Первый среди Равных
Фантастика:
аниме
фантастика: прочее
эпическая фантастика
попаданцы
5.00
рейтинг книги
Первый среди равных. Книга VIII

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

Звездная Кровь. Экзарх I

Рокотов Алексей
1. Экзарх
Фантастика:
боевая фантастика
рпг
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Экзарх I

Дракон

Бубела Олег Николаевич
5. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.31
рейтинг книги
Дракон

Девяностые приближаются

Иванов Дмитрий
3. Девяностые
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Девяностые приближаются

Точка Бифуркации IV

Смит Дейлор
4. ТБ
Фантастика:
героическая фантастика
городское фэнтези
попаданцы
5.00
рейтинг книги
Точка Бифуркации IV

Эволюционер из трущоб. Том 4

Панарин Антон
4. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 4