Философия Java3
Шрифт:
public String toStringO {
return String, format С [n$-3d]\ priority) + " Task " + id;
}
public String summaryО {
return "(" + id + ":" + priority + ")";
}
public static class EndSentinel extends PrioritizedTask { private ExecutorService exec; public EndSentinel(ExecutorService e) {
super(-l); // Минимальный приоритет в этой программе
exec = e;
public void run {
int count = 0;
for(PrioritizedTask pt : sequence) { printnb(pt.summaryO), if(++count % 5 == 0) printO.
}
printO;
print (this + " Calling shutdownNowO"); exec.shutdownNowO.
}
}
}
class PrioritizedTaskProducer implements Runnable { private Random rand = new Random(47); private Queue<Runnable> queue; private ExecutorService exec; public PrioritizedTaskProducer(
Queue<Runnable> q, ExecutorService e) { queue = q;
exec = e; //
}
public void run {
// Неограниченная очередь без блокировки. // Быстрое заполнение случайными приоритетами: for(int i = 0; i < 20; i++) {
queue.add(new PrioritizedTask(rand.nextInt(10))); Thread.yieldO;
}
// Добавление высокоприоритетных задач: try {
for(int i = 0; i < 10; i++) {
TimeUnit.MILLISECONDS.sleep(250); queue.add(new PrioritizedTask(lO)).
}
// Добавление заданий, начиная с наименьших приоритетов: for(int i = 0; i < 10; i++)
queue.add(new PrioritizedTask(i)); // Предохранитель для остановки всех задач: queue.add(new PrioritizedTask EndSentinel(exec)); } catchdnterruptedException e) {
// Приемлемый вариант выхода
}
print("Завершение PrioritizedTaskProducer");
}
}
class PrioritizedTaskConsumer implements Runnable { private PriorityBlockingQueue<Runnable> q; public PrioritizedTaskConsumer(
PriorityBlockingQueue<Runnable> q) { this.q = q;
}
public void run {
while('Thread interruptedO)
// Использование текущего потока для запуска задачи q.takeO run. } catch(InterruptedException e) {
// Приемлемый вариант выхода
}
print("Завершение PrioritizedTaskConsumer").
}
}
public class PriorityBlockingQueueDemo {
public static void main(String[] args) throws Exception { Random rand = new Random(47);
ExecutorService exec = Executors newCachedThreadPoolО, PriorityBlockingQueue<Runnable> queue =
new PriorityBlockingQueue<Runnable>; exec execute(new PrioritizedTaskProducer(queue. exec)), exec execute(new PrioritizedTaskConsumer(queue)),
}
} ///:-
Как и в предыдущем примере, последовательность создания объектов 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"),