一、execute /submit 代码示例1. execute无返回值异常直接打印日志public class ThreadPoolDemo { public static void main(String[] args) { ExecutorService pool Executors.newFixedThreadPool(2); // execute不需要返回结果 pool.execute(() - { System.out.println(execute任务执行); int num 1 / 0; // 抛出算术异常 }); } }现象任务抛异常自动打印异常堆栈日志worker 线程销毁重建。2. submit需要返回值异常存在 Futureget 才抛public class ThreadPoolDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService pool Executors.newFixedThreadPool(2); FutureInteger future pool.submit(() - { System.out.println(submit任务执行); int num 1 / 0; return 100; }); // 不调用get没有任何报错、日志异常被吞 // future.get(); // 执行get这一行才抛出ExecutionException } }结论要拿结果就用 submit不调用 get异常静默丢失。二、线程池【线程饥饿死锁】完整代码示例场景newFixedThreadPool(5)固定 5 条线程外层异步任务内部再次往同一个池子 submit 内层任务然后 get 阻塞import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class ThreadPoolDeadLockDemo { // 同一个线程池总共5个线程不能扩容 private static final ExecutorService pool Executors.newFixedThreadPool(5); public static void main(String[] args) { // 提交5个【外层大任务】刚好占满5条worker线程 for (int i 0; i 5; i) { pool.submit(() - { System.out.println(外层任务开始执行 Thread.currentThread().getName()); try { // 在外层异步任务内部继续往同一个线程池提交【内层小任务】 FutureString innerFuture pool.submit(() - { System.out.println(内层任务运行 Thread.currentThread().getName()); return 内层任务执行完成; }); // 重点阻塞等待内层任务结果 String result innerFuture.get(); System.out.println(拿到内层结果 result); } catch (Exception e) { e.printStackTrace(); } System.out.println(外层任务执行结束); }); } } }代码运行逻辑拆解循环提交 5 个外层任务5 条线程全部被外层任务占用每个外层任务执行到pool.submit(内层任务)内层任务放入队列排队执行innerFuture.get()外层 worker 线程阻塞外层任务没跑完线程不会释放归还池子因为get需要再开启一个线程。现在 5 个 worker 全部卡在 get队列里面放了 5 个内层任务newFixedThreadPool没有非核心线程队列没满不会新建线程没有空闲线程去拿队列里的内层任务 → 内层任务永远跑不完 → get 永久阻塞全部卡死线程饥饿死锁。解决方案代码示例方案 1分开两个线程池// 外层任务池 private static final ExecutorService outerPool Executors.newFixedThreadPool(5); // 内层任务池独立线程互不抢占 private static final ExecutorService innerPool Executors.newFixedThreadPool(5); public static void main(String[] args) { for (int i 0; i 5; i) { outerPool.submit(() - { try { // 内层任务提交到另一个池子 FutureString innerFuture innerPool.submit(() - 内层完成); String res innerFuture.get(); } catch (Exception e) { e.printStackTrace(); } }); } }面试背诵总结execute不需要返回结果任务异常直接打印堆栈日志。submit需要获取返回结果异常保存在 Future 对象调用 get 时才抛出包装异常不调用 get 异常会静默丢失。死锁场景同一个线程池异步任务内部再次提交新任务并且调用 get 阻塞等待。线程全部被外层任务占住、阻塞不释放队列内层任务无线程执行发生线程饥饿死锁。