- 常见面试题
线程池中的execute和submit方法都是用于向线程池提交任务以异步执行,但它们之间存在一些关键的区别,主要包括返回值、异常处理、方法重载以及适用场景等方面。以下是对这些区别的详细解析:
- 返回值
- execute方法:此方法只接受Runnable类型的任务,并且没有返回值。
一旦任务被提交给线程池,execute方法会立即返回,而不会等待任务执行完成。 - submit方法:此方法更为灵活,可以接受Runnable或Callable类型的任务。
对于Runnable任务,submit方法会返回一个Future<?>对象,
虽然这个Future对象的get()方法调用通常会返回null,但它仍然可以用于检查任务是否完成。
对于Callable任务,submit方法会返回一个Future对象,
其中T是Callable任务返回结果的类型,通过调用Future对象的get()方法可以获取到任务执行的结果。
- 异常处理
- execute方法:如果任务在执行过程中抛出异常,这个异常不会被execute方法直接抛出,而是会被捕获并记录。
通常,这些异常会被传递给线程池的未捕获异常处理器(UncaughtExceptionHandler)进行处理。 - submit方法:对于submit方法提交的任务,
如果任务执行过程中抛出异常,这个异常会被包装在ExecutionException中,
并在调用Future对象的get()方法时重新抛出。这使得开发者能够更容易地捕获和处理这些异常。
- 方法重载
- execute方法:该方法没有重载形式,只接受一个Runnable类型的参数。
- submit方法:submit方法有多种重载形式,可以接受Runnable、Callable或其他类型的任务作为参数,
并返回相应的Future对象。这使得submit方法在处理不同类型任务时更加灵活。
- 适用场景
- execute方法:适用于那些不需要关心任务执行结果和异常处理的场景。
当开发者只是简单地将任务提交给线程池执行,而不关心任务何时完成或执行结果时,可以使用execute方法。 - submit方法:适用于需要获取任务执行结果或进行异常处理的场景。
当开发者需要等待任务完成并获取其结果,或者需要捕获和处理任务执行过程中抛出的异常时,应该使用submit方法。
总结
线程池中的execute和submit方法在返回值、异常处理、方法重载以及适用场景等方面存在显著的区别。开发者在选择使用哪个方法时,应根据具体的需求和场景进行权衡。一般来说,submit方法提供了更多的功能和灵活性,因此在需要获取任务执行结果或进行异常处理的场景中更为适用;而execute方法则更加简单直接,适用于那些不需要关心这些方面的场景。
@Component
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor threadPool() {
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 60;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
return new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
}
@Component
public class InvokeMethod {
public Integer cacl(Integer num) {
try {
Thread.sleep(num * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return num;
}
}
@SpringBootTest
class MiaoApplicationTests {
@Resource
private ThreadPoolConfig threadPoolConfig;
@Resource
private InvokeMethod invokeMethod;
@Test
void contextLoads() throws Exception {
ThreadPoolExecutor threadPoolExecutor = threadPoolConfig.threadPool();
List<Future<Integer>> futureList = Stream.of(1, 2, 3, 4, 5).map(item -> {
return threadPoolExecutor.submit(() -> invokeMethod.cacl(item));
}).collect(Collectors.toList());
for (Future<Integer> future : futureList) {
Integer resultNum = future.get();
log.info("resultNum = {}", resultNum);
}
}
}