из-за требуемой задержки между двумя запусками, я бы предложил java.util.Timer
или java.util.concurrent.ScheduledThreadPoolExecutor
. Timer
очень просто и идеально подходит для использование кейс. Но если дополнительные требования к планированию идентифицируются позже, один из Executor
может обрабатывать все из них. В любом случае используйте метод с фиксированной задержкой, а не метод с фиксированной ставкой.
Повторяющаяся задача polls параллельная очередь для объекта запроса. Если есть ожидающий запрос, задача выполняет его и возвращает результат через обратный вызов. Запрос для службы и обратный вызов для вызова являются членами объекта запроса.
Приложение сохраняет ссылку на общую очередь. Чтобы запланировать запрос, просто добавьте его в очередь.
Чтобы уточнить, если очередь выполнена при выполнении запланированной задачи, запрос не выполняется. Простой подход состоял бы только в том, чтобы закончить задачу, и планировщик вызовет задачу через секунду, чтобы снова проверить.
Однако это означает, что для запуска задачи может потребоваться до одной секунды, даже если в последнее время запросы не обрабатывались. Если эта ненужная задержка является невыносимой, писать собственный поток, вероятно, предпочтительнее использовать Timer
или ScheduledThreadPoolExecutor
. В вашем собственном цикле синхронизации у вас больше контроля над планированием, если вы решили блокировать пустую очередь до тех пор, пока запрос не будет доступен. Встроенные таймеры не гарантированно ждут полной секунды после предыдущего выполнения завершено; они обычно планируют относительно начало времени задачи.
Если этот второй случай - это то, что вы имеете в виду, ваш метод run()
будет содержать цикл. Каждая итерация начинается с blocking в очереди до получения запроса, а затем записывает время. После обработки запроса время снова проверяется. Если разница во времени меньше одной секунды, sleep для остатка. Эта установка предполагает, что требуется одна секунда задержки между началом одного запроса и следующей. Если требуется задержка между окончанием одного запроса и следующей, вам не нужно проверять время; просто спать в течение одной секунды.
Еще одна вещь, которую следует учитывать, заключается в том, что служба может принимать несколько запросов в одном запросе, что уменьшит накладные расходы. Если это так, воспользуйтесь этим, заблокировав take()
для первого элемента, затем используя poll()
, возможно, с очень коротким временем блокировки (5 мс или около того), чтобы узнать, делает ли приложение больше запросов. Если это так, они могут быть объединены в один запрос к службе. Если queue
является BlockingQueue<? extends Request>
, это может выглядеть примерно так:
Collection<Request> bundle = new ArrayList<Request>();
bundle.add(queue.take());
while (bundle.size() < BUNDLE_MAX) {
Request req = queue.poll(EXTRA, TimeUnit.MILLISECONDS);
if (req == null)
break;
bundle.add(req);
}
/* Now make one service request with contents of "bundle". */
я предполагаю, вы создаете приложение на рабочем столе? –
Да, это правильно! –