コード例 #1
0
  @SuppressWarnings("unchecked")
  protected <T> Task<T> submitNewTask(final Map<?, ?> flags, final Task<T> task) {
    if (task instanceof ScheduledTask)
      return (Task<T>) submitNewScheduledTask(flags, (ScheduledTask) task);

    tasksById.put(task.getId(), task);
    totalTaskCount.incrementAndGet();

    beforeSubmit(flags, task);

    if (((TaskInternal<T>) task).getJob() == null)
      throw new NullPointerException(
          "Task " + task + " submitted with with null job: job must be supplied.");

    Callable<T> job =
        new Callable<T>() {
          public T call() {
            try {
              T result = null;
              Throwable error = null;
              String oldThreadName = Thread.currentThread().getName();
              try {
                if (RENAME_THREADS) {
                  String newThreadName =
                      oldThreadName
                          + "-"
                          + task.getDisplayName()
                          + "["
                          + task.getId().substring(0, 8)
                          + "]";
                  Thread.currentThread().setName(newThreadName);
                }
                beforeStart(flags, task);
                if (!task.isCancelled()) {
                  result = ((TaskInternal<T>) task).getJob().call();
                } else throw new CancellationException();
              } catch (Throwable e) {
                error = e;
              } finally {
                if (RENAME_THREADS) {
                  Thread.currentThread().setName(oldThreadName);
                }
                afterEnd(flags, task);
              }
              if (error != null) {
                if (log.isDebugEnabled()) {
                  // debug only here, because we rethrow
                  log.debug(
                      "Exception running task " + task + " (rethrowing): " + error.getMessage(),
                      error);
                  if (log.isTraceEnabled())
                    log.trace(
                        "Trace for exception running task "
                            + task
                            + " (rethrowing): "
                            + error.getMessage(),
                        error);
                }
                throw Exceptions.propagate(error);
              }
              return result;
            } finally {
              ((TaskInternal<?>) task).runListeners();
            }
          }
        };

    // If there's a scheduler then use that; otherwise execute it directly
    Set<TaskScheduler> schedulers = null;
    for (Object tago : task.getTags()) {
      TaskScheduler scheduler = getTaskSchedulerForTag(tago);
      if (scheduler != null) {
        if (schedulers == null) schedulers = new LinkedHashSet<TaskScheduler>(2);
        schedulers.add(scheduler);
      }
    }
    Future<T> future;
    if (schedulers != null && !schedulers.isEmpty()) {
      if (schedulers.size() > 1)
        log.warn(
            "multiple schedulers detected, using only the first, for " + task + ": " + schedulers);
      future = schedulers.iterator().next().submit(job);
    } else {
      future = runner.submit(job);
    }
    // on completion, listeners get triggered above; here, below we ensure they get triggered on
    // cancel
    // (and we make sure the same ExecutionList is used in the future as in the task)
    ListenableFuture<T> listenableFuture =
        new ListenableForwardingFuture<T>(future, ((TaskInternal<T>) task).getListeners()) {
          @Override
          public boolean cancel(boolean mayInterruptIfRunning) {
            boolean result = false;
            if (!task.isCancelled()) result |= task.cancel(mayInterruptIfRunning);
            result |= super.cancel(mayInterruptIfRunning);
            ((TaskInternal<?>) task).runListeners();
            return result;
          }
        };

    ((TaskInternal<T>) task).initResult(listenableFuture);
    return task;
  }