1. 程式人生 > 程式設計 >簡單解析execute和submit有什麼區別

簡單解析execute和submit有什麼區別

1、execute 方法位於 java.util.concurrent.Executor 中

void execute(Runnable command);

2、execute 的具體實現

public void execute(Runnable command) {
    if (command == null)
      throw new NullPointerException();
    /*
     * Proceed in 3 steps:
     *
     * 1. If fewer than corePoolSize threads are running,try to
     * start a new thread with the given command as its first
     * task. The call to addWorker atomically checks runState and
     * workerCount,and so prevents false alarms that would add
     * threads when it shouldn't,by returning false.
     *
     * 2. If a task can be successfully queued,then we still need
     * to double-check whether we should have added a thread
     * (because existing ones died since last checking) or that
     * the pool shut down since entry into this method. So we
     * recheck state and if necessary roll back the enqueuing if
     * stopped,or start a new thread if there are none.
     *
     * 3. If we cannot queue task,then we try to add a new
     * thread. If it fails,we know we are shut down or saturated
     * and so reject the task.
     */
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
      if (addWorker(command,true))
        return;
      c = ctl.get();
    }
    if (isRunning(c) && workQueue.offer(command)) {
      int recheck = ctl.get();
      if (! isRunning(recheck) && remove(command))
        reject(command);
      else if (workerCountOf(recheck) == 0)
        addWorker(null,false);
    }
    else if (!addWorker(command,false))
      reject(command);
  }

3、submit 方法位於 java.util.concurrent.AbstractExecutorService 中

/**
   * @throws RejectedExecutionException {@inheritDoc}
   * @throws NullPointerException    {@inheritDoc}
   */
  public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task,null);
    execute(ftask);
    return ftask;
  }

  /**
   * @throws RejectedExecutionException {@inheritDoc}
   * @throws NullPointerException    {@inheritDoc}
   */
  public <T> Future<T> submit(Runnable task,T result) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task,result);
    execute(ftask);
    return ftask;
  }

  /**
   * @throws RejectedExecutionException {@inheritDoc}
   * @throws NullPointerException    {@inheritDoc}
   */
  public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
  }

4、submit 方式使用 Runnable 入參時的具體實現

static final class RunnableAdapter<T> implements Callable<T> {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task,T result) {
      this.task = task;
      this.result = result;
    }
    public T call() {
      task.run();
      return result;
    }
  }

5、submit 方式使用 Callable 入參時的具體實現

public FutureTask(Callable<V> callable) {
    if (callable == null)
      throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;    // ensure visibility of callable
  }

  //重寫run方法
  public void run() {
    if (state != NEW ||
      !UNSAFE.compareAndSwapObject(this,runnerOffset,null,Thread.currentThread()))
      return;
    try {
      Callable<V> c = callable;
      if (c != null && state == NEW) {
        V result;
        boolean ran;
        try {
          result = c.call();
          ran = true;
        } catch (Throwable ex) {
          result = null;
          ran = false;
          setException(ex);
        }
        if (ran)
          set(result);
      }
    } finally {
      // runner must be non-null until state is settled to
      // prevent concurrent calls to run()
      runner = null;
      // state must be re-read after nulling runner to prevent
      // leaked interrupts
      int s = state;
      if (s >= INTERRUPTING)
        handlePossibleCancellationInterrupt(s);
    }
  }

總結:

1、根據原始碼可以看到 execute 僅可以接受Runnable型別,而 submit 過載了三個方法,引數可以是 Runnable 型別、Runnable 型別+泛型T 、Callable 型別介面。

2、從上面原始碼可以看出 submit 方法實際上如果用Runnable型別的介面可以有返回值,也可以沒有返回值。

3、傳遞Runnable型別介面加泛型T會被進一步封裝,在 Executors 這個類裡面有個內部類 RunnableAdapter 實現了 Callable 介面。

4、看submit方法可以看出,submit最終也是在呼叫 execute 方法,無論是 Runnable 還是 Callable 型別介面,都會被封裝成 FutureTask 繼續執行。

5、如果使用submit方法提交,會進一步封裝成FutureTask,執行execute方法,在FutureTask裡面重寫的run方法裡面呼叫 Callable 介面的call方法。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。