面试题答案
一键面试常见问题
- 阻塞问题:
- 阐述:
get()
方法是阻塞的。如果异步任务尚未完成,调用get()
方法的线程将会被阻塞,直到任务完成并返回结果。这可能导致程序的响应性降低,特别是在主线程调用get()
方法且异步任务执行时间较长的情况下。 - 避免方式:使用
get(long timeout, TimeUnit unit)
方法,设置一个超时时间。如果在指定时间内任务没有完成,该方法将抛出TimeoutException
,调用线程不会无限期阻塞。例如:
Future<Integer> future = executorService.submit(() -> { // 模拟耗时任务 Thread.sleep(5000); return 42; }); try { Integer result = future.get(2, TimeUnit.SECONDS); System.out.println("Result: " + result); } catch (TimeoutException e) { System.out.println("Task timed out"); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }
- 阐述:
- 异常处理问题:
- 阐述:
get()
方法可能抛出InterruptedException
和ExecutionException
。InterruptedException
表示调用线程在等待任务完成时被中断;ExecutionException
封装了异步任务执行过程中抛出的异常。如果不恰当处理这些异常,可能导致程序崩溃或出现未处理的错误。 - 避免方式:在调用
get()
方法时,使用try - catch
块捕获并处理这些异常。如上述代码中,对InterruptedException
和ExecutionException
进行了捕获和适当处理。ExecutionException
可以通过getCause()
方法获取其内部封装的异常,以便进行更详细的错误处理。
- 阐述:
- 任务取消问题:
- 阐述:如果在获取结果前需要取消异步任务,
Future
接口提供的cancel(boolean mayInterruptIfRunning)
方法并非总是能顺利取消任务。如果任务已经开始执行且mayInterruptIfRunning
为false
,任务可能不会被取消,导致get()
方法仍然等待任务完成。 - 避免方式:在任务实现中合理地检查取消状态。例如,在任务内部使用
Thread.currentThread().isInterrupted()
检查线程是否被中断,当检测到中断时,及时停止任务执行。另外,在调用cancel()
方法时,根据实际需求合理设置mayInterruptIfRunning
参数。
- 阐述:如果在获取结果前需要取消异步任务,
- 内存泄漏问题:
- 阐述:如果创建了大量的
Future
对象并且没有及时处理(如获取结果或取消任务),这些Future
对象及其关联的任务可能一直占用内存,导致内存泄漏。 - 避免方式:及时调用
get()
方法获取结果或cancel()
方法取消任务,确保Future
对象不再被引用,以便垃圾回收器能够回收相关资源。可以使用合适的数据结构(如Queue
)来管理Future
对象,并定期检查和处理这些对象。
- 阐述:如果创建了大量的