Thread.start()后不能直接调用run(),因为start()才是JVM创建新线程并调度run()的唯一合法入口;而run()只是普通方法,直接调用仍在当前线程同步执行,无法实现多线程。

为什么 Thread.start() 之后不能直接调用 run()
这是新手最常踩的坑:启动线程后手动调用 run(),结果代码看似执行了,但其实仍在主线程里跑,完全没走多线程逻辑。
-
start()是 JVM 触发新线程并调度run()的唯一合法入口;调用它才会真正创建 OS 级线程 -
run()只是一个普通方法,直接调用等价于同步执行,和单线程无异 - 如果
run()抛异常,start()启动的线程会终止;而手动调用时异常会直接冒泡到调用栈上层
共享变量不加 synchronized 或 volatile 就一定出问题吗?
不一定立即出问题,但只要存在读写竞争且无同步机制,就属于未定义行为——可能在测试环境永远不复现,上线后偶发错值、丢失更新或无限循环。
-
volatile仅保证可见性和禁止重排序,不保证原子性(如i++仍是三步操作) -
synchronized锁住的是对象监视器,不是变量本身;多个线程锁不同实例对象,照样并发冲突 - JIT 编译器可能把未同步的字段缓存到寄存器,导致一个线程永远看不到另一线程的修改
用 ExecutorService 提交 Runnable 还是 Callable?
看是否需要返回结果和异常传播能力。两者底层都走线程池调度,但语义和错误处理完全不同。
-
Runnable无返回值,异常会静默吞掉(除非设置Thread.UncaughtExceptionHandler) -
Callable返回Future,可主动get()拿结果或捕获执行中抛出的异常(包装为ExecutionException) - 若任务可能超时,必须用
Callable+Future.get(long, TimeUnit);Runnable没有超时控制能力
ThreadLocal 不清理会导致内存泄漏?
会,尤其在线程池场景下非常危险。因为 ThreadLocal 的 key 是弱引用,value 是强引用;线程长期存活时,key 被回收后 value 却滞留在线程的 ThreadLocalMap 中。
BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录
立即学习“Java免费学习笔记(深入)”;
- 每次使用完务必调用
threadLocal.remove(),不要依赖set(null) - 在
try-finally块里清理,避免因异常跳过清除逻辑 - Web 应用中,Filter 或 Interceptor 是典型的
ThreadLocal使用点,必须确保请求结束前清理
线程池 + ThreadLocal 组合,漏掉一次 remove() 就可能让整个线程持有的对象无法被 GC,积累下来就是堆内存缓慢泄漏。







