17 sierpnia 2012

O tym jak DelayQueue realizuje kontrakt Iterable oraz BlockingQueue

W poprzednim wpisie Króciutko o j.u.concurrent.DelayQueue zaprezentowałem dosyć uproszczony przykład zastosowania java.util.concurrent.DelayQueue, w którym kolejka ukrywała elementy nieaktywne, co w tym konkretnym przypadku oznaczało wszystkie elementy. DelayQueue jest najzwyczajniej w świecie kolejką, która posiada dodatkową cechę, która pozwala na "widoczność" elementów, których czas "zamrożenia" minął. Stąd też, nieblokująca metoda poll() zwracała specjalną wartość - null - oznaczającą niemożność wykonania, tj. natychmiastowego zwrócenia elementu z kolejki.

Klasa j.u.c.DelayQueue posiada następujące cechy:
  • jest kolejką
  • jest nieograniczona (metoda remainingCapacity() zawsze zwraca Integer.MAX_VALUE)
  • jest blokująca (niektóre operacje manipulujące elementami kolejki, np. wspomniane poll() czy take())
  • operuje wyłącznie elementami typu j.u.concurrent.Delayed.
Zagłębiłem się w javadoc tej klasy i znalazłem inne ciekawostki, które przykuły moją uwagę. Oto przykład z nimi, a Twoim zadaniem jest odpowiedź na pytania w komentarzach. Miłej lektury!
package pl.japila.java7;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class DelayQueueMain {

    static class Conference implements Delayed {

        long delay;

        public Conference(long delay) {
            this.delay = delay;
        }

        @Override
        public int compareTo(Delayed o) {
            Conference c = (Conference) o;
            return this.getDelay() < c.getDelay() ? -1 : this.getDelay() == c.getDelay() ? 0 : 1;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return getDelay();
        }

        public long getDelay() {
            return delay;
        }

        @Override
        public String toString() {
            return String.format("Conference starts in %s days", getDelay());
        }

    }

    public static void main(String[] args) {
        DelayQueue<Conference> conferences = new DelayQueue<Conference>();
        conferences.add(new Conference(5));
        conferences.add(new Conference(10));
        conferences.add(new Conference(15));

        System.out.println("Head (delay expired furthest in the past) element: " + conferences.poll());

        // Q1: Jakie elementy zostaną wypisane na ekran?
        for (Conference conf : conferences) {
            System.out.println(conf);
        }

        // Q2: Jaki efekt po wykonaniu poniższej linii?
        System.out.println(conferences.element());

        // Q3: Co się stanie tutaj?
        conferences.add(null);
    }

}