最简多线程方式是new Thread()并调用start(),不可用run();仅能start一次;推荐传Runnable而非继承Thread;需注意命名、守护线程设置时机及共享变量的线程安全问题。

直接 new Thread() 启动线程是最简方式
Java 中最基础的多线程实现,就是创建 Thread 实例并调用 start()。注意不是 run()——调用 run() 只是普通方法执行,不会开启新线程。
常见错误现象:thread.run() 看似“跑起来了”,但实际仍在主线程中同步执行,毫无并发效果。
- 必须用
thread.start()才会触发 JVM 创建操作系统级线程 -
start()内部会自动调用run(),但这是在线程上下文中 - 一个
Thread实例只能start()一次,重复调用抛IllegalThreadStateException
Thread t = new Thread(() -> {
System.out.println("我在新线程里:" + Thread.currentThread().getName());
});
t.start(); // ✅ 正确
// t.run(); ❌ 串行执行,不并发
// t.start(); ❌ 抛异常两种构造方式:Runnable 和继承 Thread 类
新建 Thread 时,核心是提供要执行的逻辑。Java 提供两种主流路径,本质都是为了传入 Runnable。
使用场景:如果只是临时起个线程做点事,用 Lambda 或匿名内部类最轻量;如果逻辑较重、需复用或带状态,建议单独写 Runnable 实现类。
立即学习“Java免费学习笔记(深入)”;
- 方式一(推荐):传
Runnable对象 —— 符合面向接口、避免单继承限制new Thread(() -> { /* 代码 */ }).start(); - 方式二:继承
Thread并重写run()—— 仅当真需要扩展Thread行为时才用new MyThread().start();(MyThread extends Thread)
性能/兼容性影响:两种方式在运行时无差异,JVM 最终都走同一套线程调度机制。但继承 Thread 会占用你唯一的父类 slot,后续无法再继承其他类。
线程名、优先级和守护线程这些参数别忽略
默认线程名是 Thread-0、Thread-1 这类,出问题时日志里根本分不清是谁。优先级和守护属性则直接影响程序生命周期。
- 设名字:
new Thread(() -> {}, "worker-1")—— 方便排查、监控、线程 dump 分析 - 设优先级:
thread.setPriority(Thread.MAX_PRIORITY),但注意:JVM 不保证严格遵循,且不同 OS 调度策略差异大,慎用 - 设守护线程:
thread.setDaemon(true)—— JVM 退出时不等待该线程结束,适合后台服务(如日志刷盘、心跳上报),但不能用于关键业务逻辑
容易踩的坑:setDaemon(true) 必须在 start() 前调用,否则抛 IllegalThreadStateException;setPriority() 同样只对未启动线程生效。
别忘了线程安全这个隐性门槛
刚跑通两个 Thread 并发打印,不代表你就“会多线程”了。真正复杂的是共享变量访问——比如两个线程同时 ++ 一个 int count,结果大概率少于预期值。
原因在于 count++ 不是原子操作(读-改-写三步),而 Thread 类本身不提供任何同步机制。这时候就得靠 synchronized、volatile、AtomicInteger 或 ReentrantLock 来补。
最容易被忽略的一点:初学者常以为“用了 Thread 就自动线程安全”,结果在共享集合、静态字段、单例对象上栽跟头。多线程的难点从来不在“怎么启”,而在“怎么不乱”。


















