Это вопрос дизайна, и я прошу поделиться некоторыми идеями. У меня есть метод отдыха, и он запускает долгосрочные задачи (10-15 минут) Поскольку функция занимает много времени, я запускаю ее как поток, это поможет избежать тайм-аута метода, но как я могу узнать, что поток пошел не так ?
Runnable loader = new Runnable() {
public void run() {
//tasks
}
};
(new Thread(loader)).start();
Обновление: остальные службы вроде этого
@path()
beginload(){
//let thread run and return info first
//how can i know if this thread went wrong?
(new Thread(loader)).start();
return "need 15 minutes";
}
3 ответа
Концептуально должен быть способ сообщить клиенту об ошибке. Есть несколько способов сделать это. Вот три примера:
- После того, как клиент вызывает службу, служба немедленно возвращает идентификатор задания. Клиент может использовать идентификатор задания позже, чтобы запросить у службы статус (включая ошибку). Например, когда вы запускаете инстансы в AWS EC2, EC2 требуется время для обслуживания запроса, поэтому запрос на запуск возвращает так называемый «идентификатор резервирования», который можно использовать в последующих операциях (например, запрос статуса, завершение запуск и т. д.).
- Pro: можно использовать в самых разных случаях и достаточно легко реализовать.
- Против: Требуется опрос. (То есть более болтливым.)
- Клиент предлагает URI обратного вызова, который служба вызывает после завершения задания. URI обратного вызова можно либо настроить в службе, либо передать в качестве параметра запроса. (Не следует жестко кодировать URI обратного вызова в службе, поскольку службы не должны зависеть от своих клиентов.)
- Pro: все еще довольно просто и позволяет избежать опросов.
- Против: клиент должен иметь URI для вызова службы, что может быть неудобно. (Например, клиент может быть настольным приложением, а не службой, брандмауэр может предотвратить это и т. Д.)
- Клиент помещает уведомление в очередь сообщений, и клиент прослушивает эту очередь.
- Pro: избегает опроса, и клиенту не нужны конечные точки для вызова.
- Минус: больше работы по настройке (требуется инфраструктура обмена сообщениями).
Есть и другие возможности, но это типичные подходы.
Если вы хотите получить возвращаемое значение вашего потока и выбросить / перехватить возможное исключение, рассмотрите возможность использования Callable, а не Runnable
, и его можно использовать вместе с ExecutorService, которые обеспечивают большую функциональность.
Callable : A task that returns a result and may throw an exception.
Implementors define a single method with no arguments called call.
public interface Callable<V> {
V call() throws Exception;
}
Вам нужно различать разные запросы? Если нужно выполнить несколько задач, нужен ID.
Вы можете сделать что-то вроде следующего:
private static final ExecutorService es = Executors.newFixedThreadPool(10);
private static final Map<Long, Future<Void>> map = new HashMap<>();
@GET
@Path("/submit")
public Response submitTask() {
long id = System.currentTimeMillis();
Future<Void> future = es.submit(new Callable<Void>() {
public Void call() throws Exception {
// long task
// you must throw exception for bad task
return null;
}
});
map.put(id, future);
return Response.ok(id, MediaType.TEXT_PLAIN).build();
}
@GET
@Path("/status/{id}")
public Response submitTask(@PathParam("id") long id) {
Future<Void> future = map.get(id);
if (future.isDone()) {
try {
future.get();
return Response.ok("Successful!", MediaType.TEXT_PLAIN).build();
} catch (InterruptedException | ExecutionException e) {
// log
return Response.ok("Bad task!", MediaType.TEXT_PLAIN).build();
}
}
return Response.ok("Wait a few seconds.", MediaType.TEXT_PLAIN).build();
}
Это может дать вам представление. Не забудьте очистить карту от старых задач.
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.