Как и в предыдущем примере, последовательность создания объектов PrioritizedTask сохраняется в контейнере List sequence для сравнения с фактическим порядком выполнения. Метод run() делает небольшую паузу, а затем выводит информацию об объекте, а предохранитель EndSentinel выполняет те же функции, что и прежде.
PrioritizedTaskProducer и PrioritizedTaskConsumer связываются друг с другом через PriorityBlockingQueue. Так как сам блокирующий характер очереди обеспечивает всю необходимую синхронизацию, явная синхронизация не нужна — при чтении вам не нужно думать о том, содержит ли очередь элементы, потому что при отсутствии элементов очередь просто заблокирует читающую сторону.
Управление оранжереей на базе ScheduledExecutor
В главе 10 была представлена система управления гипотетической оранжереей, которая включала (отключала) различные устройства и регулировала их работу. Происходящее можно преобразовать в контекст многозадачности: каждое событие оранжереи представляет собой задачу, запускаемую в заранее заданное время. Класс ScheduledThreadPoolExecutor предоставляет именно тот сервис, который необходим для решения задачи. Используя методы schedule() (однократный запуск задачи) или scheduleAtFixedRate() (повторение задачи с постоянным промежутком), мы создаем объекты Runnable, которые должны запуститься в положенное время. Сравните это решение с тем, что приведено в главе 10, и посмотрите, насколько оно упрощается благодаря готовой функциональности ScheduledThreadPoolExecutor:
//: concurrency/GreenhouseScheduler.java
// Новая реализация innerclasses/GreenhouseController.java
// с использованием ScheduledThreadPoolExecutor.
// {Args- 5000}
import java.util.concurrent.*,
import java.util *;
public class GreenhouseScheduler {
private volatile boolean light = false, private volatile boolean water = false; private String thermostat = "Day", public synchronized String getThermostatO { return thermostat,
}
public synchronized void setThermostat(String value) { thermostat = value;
}
ScheduledThreadPoolExecutor scheduler =
new ScheduledThreadPoolExecutor(10), public void schedule(Runnable event, long delay) {
scheduler schedule(event,delay.TimeUnit MILLISECONDS);
}
public void
repeat(Runnable event, long i niti alDel ay, long period) { scheduler scheduleAtFixedRate(
event, i niti alDel ay. period, TimeUnit MILLISECONDS);
}
class LightOn implements Runnable { public void run() {
// Сюда помещается аппаратный вызов, выполняющий // физическое включение света System out.printin("Свет включен"); light = true;
}
}
class LightOff implements Runnable { public void run() {
// Сюда помещается аппаратный вызов, выполняющий // физическое выключение света. System.out.printin("Свет выключен"), light = false,
}
}
class WaterOn implements Runnable { public void run() {
// Здесь размещается код включения // системы полива.
System out printlnC"Полив включен"); water = true;
}
}
class WaterOff implements Runnable { public void run О {
// Здесь размещается код выключения // системы полива
System out.printin("Полив выключен"); water = false,
}
}
class ThermostatNight implements Runnable { public void run() {
// Здесь размещается код управления оборудованием System.out.ргШ1п("Включение ночного режима"); setThermostat("Ho4b"),
}
class ThermostatDay implements Runnable { public void run() {
// Здесь размещается код управления оборудованием System out рпп^пСВключение дневного режима"), setThermostatCfleHb"),
}
}
class Bell implements Runnable {
public void run() { System.out.println("Вам!"), }
}
class Terminate implements Runnable { public void run() {
System out ргШ1п("Завершение"); scheduler shutdownNowO;
// Для выполнения этой операции необходимо запустить // отдельную задачу, так как планировщик был отключен-new ThreadО {
public void runО {
for(DataPoint d • data)
System.out.println(d);
}
}. startO;
}
}
// Новая возможность: коллекция данных static class DataPoint {
final Calendar time; final float temperature; final float humidity;
public DataPoint(Calendar d, float temp, float hum) { time = d;
temperature = temp; humidity = hum;
}
public String toStringO {
return time getTimeO + String.formate
" температура: %l$.lf влажность: *2$.2f". temperature, humidity);
}
}
private Calendar lastTime = Calendar.getlnstanceO; { // Регулировка даты до получаса
1astTime.set(Calendar.MINUTE, 30); lastTime set(Calendar.SECOND. 00);
}
private float lastTemp = 65.Of.
private int tempDirecti on = +1;
private float lastHumidity = 50 Of;
private int humidityDirecti on = +1;
private Random rand = new Random(47);
List
new ArrayList
System.out.println("Сбор данных"); synchronized(GreenhouseScheduler.this) {
1astTi me.set(Ca1enda r. MINUTE.
lastTime.get(Calendar.MINUTE) + 30); // С вероятностью 1/5 происходит смена направления: if(rand.nextlnt(5) == 4)