簡單解析execute和submit有什麼區別
阿新 • • 發佈:2020-11-11
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方法。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。