最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java 中创建线程的方式如何影响程序的执行流程控制
时间:2026-07-10 10:31:52 编辑:袖梨 来源:一聚教程网
Java线程创建方式不改变执行逻辑,但影响控制主体、启动时机、结果获取及主线程节奏;start()是并发开关,调用run()仅为同步执行;继承Thread耦合度高且受限,Runnable/Callable实现任务与线程解耦,线程池则通过策略驱动流程控制。
Java 中线程创建方式本身不直接改变程序的执行流程控制逻辑,但会显著影响“谁在控制流程”“何时开始执行”“能否获取结果”以及“是否干扰主线程节奏”。关键不在“怎么写”,而在于“启动时机”和“任务与线程的耦合程度”。
start() 才是真正开启并发的开关
无论用哪种方式创建线程对象(继承 Thread、实现 Runnable、Callable 或用线程池),只要没调用 start(),它就只是一个普通 Java 对象,不会产生新执行流。调用 run() 方法只是同步执行,等同于普通方法调用,主线程必须等它结束才能继续——这完全不是多线程。
- 调用 start() 后,JVM 请求操作系统创建内核线程,该线程进入就绪状态,由 OS 调度执行 run();主线程立即向下运行,不受阻塞
- 重复调用 start() 会抛出 IllegalThreadStateException,因为线程状态只能从 NEW → RUNNABLE 一次
- 哪怕线程刚 start 就 sleep(1000),主线程仍可能先打印日志、发请求、甚至结束程序
继承 Thread 类:线程即任务,控制权紧耦合
这种方式把“线程生命周期管理”和“业务逻辑”写进同一个类。你通过 this.start() 启动,也通过 this.interrupt() 控制;但缺点明显:
- Java 单继承限制:一旦继承 Thread,就无法再继承其他类
- 无法复用任务:每个线程实例绑定唯一任务,不能被多个线程共享执行
- 没有返回值:run() 是 void,执行结果无法回传,也无法捕获异常(除非自己 try-catch)
实现 Runnable / Callable:任务与线程解耦,流程更可控
Runnable 把“做什么”(任务)和“谁来做”(线程)分开。同一个 Runnable 实例可被多个 Thread 对象包装并启动,适合批量提交同类任务。
立即学习“Java免费学习笔记(深入)”;
- Runnable 适合无返回、不抛受检异常的场景;主线程无法得知其执行结果
- Callable + Future 配合 ExecutorService,能获取返回值、响应中断、统一处理异常,让主线程可主动等待或超时取消
- 例如 submit(callable).get(3, TimeUnit.SECONDS) —— 主线程最多等 3 秒,超时则继续,不卡死
线程池方式:执行流程从“手动调度”变为“策略驱动”
不用 new Thread().start(),而是交由 ExecutorService 统一管理。此时流程控制不再依赖单个线程的生命周期,而由线程池参数决定:
- 核心线程常驻,新任务来时优先复用,避免频繁创建销毁开销
- 任务先入队列,队列满才扩容非核心线程;若队列无界,maximumPoolSize 可能永远不生效
- 拒绝策略(如 CallerRunsPolicy)会让主线程亲自执行任务,形成天然背压,防止系统过载
- shutdown() 和 awaitTermination() 让主线程能优雅等待所有任务完成,比逐个 join 更简洁可靠