Это вопрос дизайна, и я прошу поделиться некоторыми идеями. У меня есть метод отдыха, и он запускает долгосрочные задачи (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";        
}
1
user3644708 30 Янв 2015 в 20:22

3 ответа

Лучший ответ

Концептуально должен быть способ сообщить клиенту об ошибке. Есть несколько способов сделать это. Вот три примера:

  1. После того, как клиент вызывает службу, служба немедленно возвращает идентификатор задания. Клиент может использовать идентификатор задания позже, чтобы запросить у службы статус (включая ошибку). Например, когда вы запускаете инстансы в AWS EC2, EC2 требуется время для обслуживания запроса, поэтому запрос на запуск возвращает так называемый «идентификатор резервирования», который можно использовать в последующих операциях (например, запрос статуса, завершение запуск и т. д.).
    • Pro: можно использовать в самых разных случаях и достаточно легко реализовать.
    • Против: Требуется опрос. (То есть более болтливым.)
  2. Клиент предлагает URI обратного вызова, который служба вызывает после завершения задания. URI обратного вызова можно либо настроить в службе, либо передать в качестве параметра запроса. (Не следует жестко кодировать URI обратного вызова в службе, поскольку службы не должны зависеть от своих клиентов.)
    • Pro: все еще довольно просто и позволяет избежать опросов.
    • Против: клиент должен иметь URI для вызова службы, что может быть неудобно. (Например, клиент может быть настольным приложением, а не службой, брандмауэр может предотвратить это и т. Д.)
  3. Клиент помещает уведомление в очередь сообщений, и клиент прослушивает эту очередь.
    • Pro: избегает опроса, и клиенту не нужны конечные точки для вызова.
    • Минус: больше работы по настройке (требуется инфраструктура обмена сообщениями).

Есть и другие возможности, но это типичные подходы.

3
30 Янв 2015 в 18:35

Если вы хотите получить возвращаемое значение вашего потока и выбросить / перехватить возможное исключение, рассмотрите возможность использования 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;
}
1
Paul Lo 30 Янв 2015 в 17:26

Вам нужно различать разные запросы? Если нужно выполнить несколько задач, нужен 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();

}

Это может дать вам представление. Не забудьте очистить карту от старых задач.

2
Paul Vargas 30 Янв 2015 в 18:16