休息方法需要很长时间

时间:2015-01-30 17:22:00

标签: java rest

这是一个设计问题,我想要一些想法。 我有一个休息方法,它将触发长时间的任务(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 个答案:

答案 0 :(得分:3)

从概念上讲,服务必须有一种方法来向客户端传达故障。有多种方法可以做到这一点。以下是三个例子:

  1. 客户端调用服务后,服务会立即返回作业ID。客户端稍后可以使用作业ID来查询服务状态(包括错误)。例如,当您在AWS EC2上启动实例时,EC2需要一段时间来为请求提供服务,因此启动请求会返回一个所谓的“预留ID”,您可以在后续操作中使用它(例如查询状态,终止发射等)。
    • Pro:可用于各种情况,并且易于实施。
    • Con:需要投票。 (即更健谈。)
  2. 客户端提供服务在作业完成时调用的回调URI。回调URI可以配置到服务中,也可以作为请求参数传递。 (不要对服务中的回调URI进行硬编码,因为服务不应该依赖于他们的客户端。)
    • 专业:还很简单,并避免轮询。
    • Con:客户端必须拥有要调用的服务的URI,这可能不方便。 (例如,客户端可能是桌面应用程序而不是服务,防火墙可能会阻止它等)。
  3. 客户端将通知推送到消息队列,客户端侦听该队列。
    • Pro:避免轮询,客户端不需要端点呼叫。
    • Con:需要设置更多工作(需要消息传递基础架构)。
  4. 还有其他可能性,但这些是典型的方法。

答案 1 :(得分:2)

您需要区分不同的请求吗?如果要执行多个任务,则需要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 :(得分:1)

如果要获取线程的返回值并抛出/捕获可能的异常,请考虑使用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;
}