start()不能重复调用,因线程生命周期单向不可逆,重复调用抛IllegalThreadStateException;应复用Runnable而非Thread实例。

直接用 Thread 类创建线程时,为什么 start() 不能重复调用?
因为线程对象的生命周期是单向的:新建 → 就绪 → 运行 → 死亡。一旦 start() 执行过,线程状态就不可逆;再次调用会抛出 IllegalThreadStateException。
- 不要手动调用
run()来“模拟启动”,那只是普通方法调用,不会开启新线程 - 如果需要多次执行相同逻辑,应封装成任务(如
Runnable),交由新Thread实例处理 -
Thread实例不可复用,但Runnable实例可以反复传给不同Thread
Runnable task = () -> System.out.println("Hello from thread");
new Thread(task).start(); // ✅
new Thread(task).start(); // ✅ 另起一个线程
// new Thread(task).start(); // ❌ 同一个 Thread 实例不能 start 两次用 ExecutorService 管理线程池时,shutdown() 和 shutdownNow() 的区别在哪?
前者是温和关闭:拒绝新任务,等正在运行和队列中已提交的任务完成;后者是强制中断:尝试停止所有正在执行的任务,并清空任务队列。
-
shutdown()后调用submit()会立即抛出RejectedExecutionException -
shutdownNow()不保证一定能中断正在运行的线程——它只是对每个线程调用interrupt(),具体是否响应取决于任务内部是否检查中断状态 - 务必配合
awaitTermination()等待终止完成,否则 JVM 可能提前退出
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(() -> { while (!Thread.currentThread().isInterrupted()) { /* work */ } });
pool.shutdown(); // 或 shutdownNow()
if (!pool.awaitTermination(5, TimeUnit.SECONDS)) {
pool.shutdownNow(); // 超时后强制收尾
}为什么 ThreadLocal 不能替代同步,反而容易引发内存泄漏?
ThreadLocal 提供的是线程隔离的变量副本,不是线程安全的共享机制。它的泄漏风险主要来自线程池中长期存活的线程持有 ThreadLocalMap 引用,而 key 是弱引用、value 是强引用——若未手动 remove(),value 无法被回收。
- 在使用线程池的场景下(如 Web 容器、定时任务),必须在任务结束前显式调用
threadLocal.remove() - 不要把大对象塞进
ThreadLocal,尤其避免存入上下文或连接类资源 -
ThreadLocal.withInitial()创建的实例仍需手动清理,初始化逻辑不改变生命周期管理责任
private static final ThreadLocalformatter = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd")); public String format(Date date) { try { return formatter.get().format(date); } finally { formatter.remove(); // ⚠️ 必须有,尤其在线程池中 } }
线程中断机制中,interrupt()、isInterrupted() 和静态 interrupted() 怎么选?
三者都围绕中断标志位操作,但行为差异明显:interrupt() 设置标志;isInterrupted() 仅读取且不清除;静态 interrupted() 读取并清除标志——而且只对当前线程有效。
BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录
立即学习“Java免费学习笔记(深入)”;
- 阻塞方法(如
sleep()、wait()、join())检测到中断会抛出InterruptedException并自动清除中断状态 - 捕获
InterruptedException后,若不重新中断(Thread.currentThread().interrupt()),上层调用者将丢失中断信号 - 轮询检查中断时优先用
Thread.currentThread().isInterrupted(),避免误清状态
while (!Thread.currentThread().isInterrupted()) {
doWork();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
break;
}
}线程模型本身不复杂,真正难的是状态边界判断——比如“任务是否真的结束了”“中断信号有没有被吞掉”“池子里的线程还持有哪些隐式引用”。这些地方没日志、不调试,光看代码很难确认。









