线程池中方法execute和submit的区别

Yi Java 2023-02-14 88

一、方法上的区别

传入参数
  • execute:只能传入 Runnable 任务;
  • submit:可以传入 Callable,Runnable 两种类型的任务。
返回值
  • execute:没有返回值;
  • submit:返回 Future。
运行时异常
  • execute:线程池内部将异常处理掉了,如果需要处理异常,需在任务中自行捕获处理;
  • submit:会将异常暂存,并在调用Future的get方法的时候抛出。

二、API实现上的区别

  • execute : Executor 接口中定义,并在 ThreadPoolExecutor 类中初步实现;
  • submit :ExecutorService 接口中定义,并在 AbstractExecutorService 抽象类中初步实现,但最终还是调用的 execute 方法;
  • ThreadPoolExecutor 继承 AbstractExecutorService 抽象类,AbstractExecutorService 实现 ExecutorService 接口,ExecutorService 继承 Executor 接口。

三、相关接口或类

public interface Executor {
    void execute(Runnable command);
}

public interface ExecutorService extends Executor {
    ...
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    ...
}

public abstract class AbstractExecutorService implements ExecutorService {
    ...
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    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;
    }
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
    ...
}

public class ThreadPoolExecutor extends AbstractExecutorService {
    ...
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        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);
    }
    ...
}