Интерфейс Delayed содержит единственный метод getDelay(), который сообщает, сколько времени осталось до истечения задержки или как давно задержка истекла. Метод заставляет нас использовать класс TimeUnit, потому что его аргумент относится именно к этому типу. Впрочем, этот класс очень удобен, поскольку он позволяет легко преобразовывать единицы без каких-либо вычислений. Например, значение delta хранится в миллисекундах, а метод Java SE5 System.nanoTime() выдает значение в наносекундах. Чтобы преобразовать значение delta, достаточно указать исходные и итоговые единицы:
NANOSECONDS.convert(delta. MILL ISECONDS);
В getDelay() желаемые единицы передаются в аргументе unit. Аргумент используется для преобразования времени задержки во временные единицы, используемые вызывающей стороной.
Для выполнения сортировки интерфейс Delayed также наследует интерфейс Comparable, поэтому необходимо реализовать метод compareToQ для выполнения осмысленных сравнений. Методы toStringO и summary() обеспечивают форматирование вывода.
Из выходных данных видно, что порядок создания задач не влияет на порядок их выполнения — вместо этого задачи, как и предполагалось, выполняются в порядке следования задержек.
PriorityBlockingQueue
Фактически класс PriorityBlockingQueue представляет приоритетную очередь с блокирующими операциями выборки. В следующем примере объектами в приоритетной очереди являются задачи, покидающие очередь в порядке приоритетов. Для определения этого порядка в класс PrioritizedTask включается поле priority:
//: concurrency/PriorityBlockingQueueDemo.java import java.util.concurrent.*; import java.util.*;
import static net.mindview.util.Print.*;
class PrioritizedTask implements Runnable, Comparable
new ArrayLi st
}
public int compareTo(PrioritizedTask arg) { return priority < arg.priority ? 1 ;
(priority > arg.priority ? -1 : 0);
}
public void run() { try {
Ti mellni t. MILLI SECONDS. s 1 eep (rand. next I nt (250)); } catch(InterruptedException e) {
// Приемлемый вариант выхода
}
print(this);
}
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
Queue
exec = e; // Используется для EndSentinel
}
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
PriorityBlockingQueue
}
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
new PriorityBlockingQueue
}
} ///:-