Reader / Writer с помощью wait и уведомляет, где читатель может извлечь из очереди только если была достигнута временная метка элемента

У меня есть приоритетная очередь (с синхронизированным доступом) задач. Каждое задание имеет время, в которое оно должно быть выполнено. Когда задача в начале очереди должна быть выполнена, она должна быть извлечена из очереди, но не раньше, так как что-то может быть добавлено вперед в очереди. (т.е. с более ранней меткой времени). Также задание может быть удалено из Q до того, как оно должно быть выполнено.

Я думаю, что так много (sudo code)

public synchronized task Q.get(){
    while Q.empty(){
        wait();
    }
    // queue is not empty
    if (Q.head.time.isBefore(now)){ // task at head of Q is due to be done
        return Q.pop();
    }else{
        // THIS IS WHERE IM STUCK ***
    }

В точке *:

Я мог бы написать код для сна до времени выполнения задачи во главе очереди, а затем принять его. Проблема в том, что у нас есть блокировка на Q, и поэтому никакие задачи не могут быть добавлены, пока мы спим?? Кроме того, если что-то будет добавлено (хотя я не уверен, что это возможно) в начало очереди, то читатель будет спать слишком долго.

Я также подумал, что мог бы снова написать код для wait() на Q, но после установки таймера (отдельный поток, принадлежащий очереди только для Q.notify во время выполнения задачи во главе очереди). Проблема, которую я вижу с этим, состоит в том, что, если что-то помещается во главе Q, мы прерывали бы таймер и уведомляли бы о Q, тогда читатель взял бы новое задание головы, не проверяя его время.

Любая помощь будет очень признательна, спасибо заранее. Я довольно неопытен в этом, поэтому, пожалуйста, исправьте любые неправильные предположения и т. Д.

Редактировать. Класс читателя, просто зацикленный, получает следующую задачу, вызывая Q.get() и выполняя ее действия.

2 ответа

Я не знаю, как ваш код работает с этим методом, но вы могли бы

  1. вернуть ноль в вашем другом или
  2. добавить цикл, который проверяет, должна ли первая задача быть выполнена к настоящему времени.

Код для второго подхода будет выглядеть так:

public synchronized task Q.get(){
    while Q.empty(){
        wait();
    }
    // queue is not empty
    while (!Q.head.time.isBefore(now)){
        //instead of writing 100 you can calculate the time between now 
        //and the first scheduled task
        wait(100); 
    }
    return Q.pop();
}

В пакете java.util.concurrent много полезных классов. Посмотрите на PriorityBlockingQueue:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/PriorityBlockingQueue.html

Вы можете запустить два потока - один поток, который пишет в очередь, и второй, который читает из очереди. Содержит метод take() который блокирует, пока в очереди нет чего-то - так что вам не нужно wait(),

Если время не раньше, теперь вы можете просто offer() взятый объект возвращается в очередь. Если порядок ваших объектов основан на времени, он будет сохранен в правильном положении в очереди.

Порядок вашего объекта может быть определен с помощью Comparator с помощью этого конструктора:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/PriorityBlockingQueue.html, java.util.Comparator)

Если вы мало знаете об интерфейсах Comparable и Comparator, взгляните на:

Java: сравнимо с компаратором

Это может быть также интересно для вас:

http://tutorials.jenkov.com/java-util-concurrent/delayqueue.html

Другие вопросы по тегам