线程池任务提交方法submit()和execute()的区别

结论

  1. 返回值:execute() 没有返回值,submit() 有返回值Future,并且结合Callable任务指定泛型,可以通过future.get()拿到对应Callable返回的对象。

  2. 接受的任务类型:execute() 方法只能接受Runnable类型,submit() 方法可以接受Runnable和Callable类型,但是因为Runnable类型的run方法返回值是void,所以future.get()的会是null。

  3. 抛出异常:

    • execute中的是Runnable接口的实现,所以只能使用try、catch来捕获CheckedException,通过实现UncaughtExceptionHande接口处理UncheckedException,即和普通线程的处理方式完全一致。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Runnable runnableTask = new Runnable() {
    @Override
    public void run() {
    int i = 1/0;
    }
    };
    for(int i = 0; i < 100; i++) {
    service.execute(runnableTask);
    }

    运行结果:

    image-20211225213059401

    • submit提交的无论是Runnable还是Callable任务,如果不调用future.get()都会吃掉异常,需要对异常进行捕获:
    1
    2
    3
    4
    5
    6
    7
    8
    for(int i = 0; i < 100; i++) {
    Future<?> future = service.submit(runnableTask);
    try {
    System.out.println(future.get());
    }catch (Exception e) {
    System.err.println(e);
    }
    }
    • 运行结果:

    image-20211225214838630

demo代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(16);

Runnable runnableTask = new Runnable() {
@Override
public void run() {
int i = 1/0;
}
};

Callable<String> callableTask = new Callable() {
@Override
public String call() throws Exception {
int i = 1/0;
return "callableTask---当前线程:" + Thread.currentThread().getName();
}
};

for(int i = 0; i < 100; i++) {
// service.execute(runnableTask);
Future<?> future = service.submit(runnableTask);
try {
System.out.println(future.get());
}catch (Exception e) {
System.err.println(e);
}
}

service.shutdown();
}