news 2026/4/3 5:06:17

JAVA|智能仿真并发项目-进程与线程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JAVA|智能仿真并发项目-进程与线程

文章目录

    • 一、核心概念:程序、进程、线程
      • 1.1 基本定义
      • 1.2 核心关系
    • 二、Java 实现线程的三种方式
      • 2.1 方式 1:继承 `Thread` 类
        • 2.1.1 实现步骤
        • 2.1.2 完整代码示例
        • 2.1.3 核心注意点
      • 2.2 方式 2:实现 `Runnable` 接口(推荐)
        • 2.2.1 实现步骤
        • 2.2.2 完整代码示例
        • 2.2.3 核心优势
      • 2.3 方式 3:实现 `Callable` 接口
        • 2.3.1 适用场景
        • 2.3.2 实现步骤
        • 2.3.3 完整代码示例
    • 三、Thread vs Runnabl
    • 四、线程的生命周期
      • 4.1 生命周期状态
      • 4.2 核心规则
    • 五、总结

一、核心概念:程序、进程、线程

1.1 基本定义

概念本质资源占用作用
程序存储在磁盘上的静态文件(代码文件 + 数据文件)无(仅占用磁盘空间)待执行的指令集合,无法解决问题
进程正在运行的程序,操作系统进行资源分配的最小单元独立内存空间、CPU、IO 等调度系统资源解决具体问题
线程进程的组成部分,CPU 调度执行任务的最小单元共享所属进程的所有资源实现进程内的并发任务

1.2 核心关系

  • 一个进程至少包含一个线程(主线程,如main方法对应的线程),也可包含多个线程
  • 进程之间内存隔离,线程之间内存共享(多线程的核心优势)
  • 操作系统负责管理进程和线程的调度(CPU 时间片轮转)

二、Java 实现线程的三种方式

2.1 方式 1:继承Thread

2.1.1 实现步骤
  1. 定义类继承java.lang.Thread
  2. 重写run()方法(线程的核心执行逻辑,无返回值)
  3. 创建自定义线程类对象,调用start()方法启动线程(不可直接调用run()
2.1.2 完整代码示例
publicclassMyThreadextendsThread{// 线程名称StringthreadName;// 构造方法初始化线程名称publicMyThread(StringthreadName){this.threadName=threadName;}// 重写run方法@Overridepublicvoidrun(){// 模拟线程执行的循环任务for(inti=0;i<100;i++){// 输出线程名称和循环次数System.out.println(threadName+"--"+i);// 休眠10ms,放大线程切换效果try{Thread.sleep(10);}catch(InterruptedExceptione){Thread.currentThread().interrupt();e.printStackTrace();}}}// 测试方法publicstaticvoidmain(String[]args){// 创建线程实例MyThreadmt1=newMyThread("线程A");MyThreadmt2=newMyThread("线程B");// 启动线程mt1.start();mt2.start();// 错误示例:重复启动同一线程,会报错// mt1.start();// 错误示例:直接调用run(),仅为普通方法调用,不会创建新线程// mt1.run();}}
2.1.3 核心注意点
  • start():触发线程创建,等待 CPU 调度,由 JVM 调用run()
  • run():普通方法,直接调用会在主线程中同步执行
  • 单继承限制:Java 不支持多继承,继承Thread后无法继承其他类

2.2 方式 2:实现Runnable接口(推荐)

2.2.1 实现步骤
  1. 定义类实现java.lang.Runnable接口
  2. 重写run()方法(与 Thread 类的run()规则一致)
  3. 创建自定义Runnable实例,作为参数传入Thread构造方法
  4. 调用Thread对象的start()方法启动线程
2.2.2 完整代码示例
publicclassMyRunimplementsRunnable{// 共享变量(多个线程共用一个MyRun实例时,该变量会被共享)intcount=0;StringtaskName;publicMyRun(StringtaskName){this.taskName=taskName;}// 重写run方法@Overridepublicvoidrun(){// 模拟任务执行for(inti=0;i<100;i++){// 多线程共享countcount++;System.out.println(Thread.currentThread().getName()+" | "+taskName+"--"+i+" | 累计计数:"+count);try{Thread.sleep(10);}catch(InterruptedExceptione){Thread.currentThread().interrupt();e.printStackTrace();}}System.out.println(taskName+" 执行完成,最终计数:"+count);}// 测试方法publicstaticvoidmain(String[]args){// 场景1:多个线程执行同一个任务(共享数据)MyRuntask=newMyRun("共享任务");Threadt1=newThread(task,"线程C");Threadt2=newThread(task,"线程D");t1.start();t2.start();// 场景2:多个线程执行不同任务(独立数据)MyRuntask1=newMyRun("独立任务1");MyRuntask2=newMyRun("独立任务2");Threadt3=newThread(task1,"线程E");Threadt4=newThread(task2,"线程F");t3.start();t4.start();}}
2.2.3 核心优势
  • 无单继承限制:实现接口后仍可继承其他类
  • 任务与线程解耦:Runnable封装任务逻辑,Thread负责执行,符合 “单一职责原则”
  • 支持数据共享:多个Thread可共用一个Runnable实例,实现线程间数据共享

2.3 方式 3:实现Callable接口

2.3.1 适用场景

有返回值,可以完成需要获取线程执行结果任务。

2.3.2 实现步骤
  1. 定义类实现java.util.concurrent.Callable<V>接口(V为返回值类型)
  2. 重写call()方法(有返回值)
  3. 创建Callable实例,封装到FutureTask<V>
  4. FutureTask传入Thread构造方法,调用start()启动线程
  5. 通过FutureTask.get()获取线程执行结果
2.3.3 完整代码示例
importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;publicclassMyCallimplementsCallable<Integer>{intstart;intend;publicMyCall(intstart,intend){this.start=start;this.end=end;}@OverridepublicIntegercall()throwsException{intsum=0;for(inti=start;i<=end;i++){sum+=i;Thread.sleep(5);}returnsum;}// 测试方法publicstaticvoidmain(String[]args){// 创建Callable任务:计算1-100的和Callable<Integer>callable=newMyCall(1,100);// 封装为FutureTask(实现了Runnable接口)FutureTask<Integer>futureTask=newFutureTask<>(callable);// 启动线程Threadt=newThread(futureTask);t.start();// 获取执行结果try{Integerresult=futureTask.get();System.out.println("1-100的和:"+result);}catch(InterruptedException|ExecutionExceptione){e.printStackTrace();}}}

三、Thread vs Runnabl

继承 Thread 类实现 Runnable 接口
继承限制受限于 Java 单继承无继承限制,可继承其他类
耦合性线程与任务耦合(类既是线程也是任务)线程与任务解耦(Runnable 是任务,Thread 是执行器)
数据共享需通过静态变量实现,代码复杂多个 Thread 共用一个 Runnable 实例,天然支持共享
代码扩展性差(单继承限制)好(可实现多接口)
适用场景简单独立任务,无需继承其他类复杂任务、需共享数据、需继承其他类

总结

  1. 继承Thread类受单继承限制,实现Runnable接口更灵活
  2. Runnable接口实现了任务与线程的解耦
  3. Runnable支持多个线程共享同一个任务实例,便于线程间数据共享
  4. 一般情况下更推荐使用Runnable接口

四、线程的生命周期

4.1 生命周期状态

状态说明
新建(New)创建 Thread 对象后,未调用start()前的状态
就绪(Runnable)调用start()后,线程进入就绪队列,等待 CPU 调度
运行(Running)CPU 分配时间片,线程执行run()方法中的逻辑
阻塞(Blocked)线程因等待锁、IO、休眠等原因暂停执行,释放 CPU 资源
终止(Terminated)线程执行完run()方法,或因异常终止,生命周期结束

4.2 核心规则

  • 线程从 “新建” 到 “终止” 只能一次,同一个 Thread 对象不能重复调用start()
  • 线程的状态切换由 JVM 和操作系统共同控制,无法手动干预(如无法强制让线程从 “阻塞” 转为 “运行”)

五、总结

  1. 核心概念:进程是资源分配单位,线程是 CPU 调度单位,多线程共享进程内存
  2. 实现方式:继承 Thread(简单但受限)、实现 Runnable(推荐,灵活共享)、实现 Callable(有返回值)
  3. 关键规则:启动线程用start()而非run(),线程生命周期仅一次,Runnable 天然支持数据共享
  4. 学习方向:线程安全(同步锁)、线程池、并发工具类(CountDownLatchCyclicBarrier)等
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/13 10:28:47

NewBie-image-Exp0.1推理卡顿?CUDA 12.1算力优化实战指南

NewBie-image-Exp0.1推理卡顿&#xff1f;CUDA 12.1算力优化实战指南 你是否也遇到过这样的情况&#xff1a;刚拉取完NewBie-image-Exp0.1镜像&#xff0c;满怀期待地执行python test.py&#xff0c;结果等了快两分钟才出图&#xff1f;终端里GPU利用率忽高忽低&#xff0c;显…

作者头像 李华
网站建设 2026/3/26 23:49:23

拖拽上传太方便!这些快捷操作你知道吗

拖拽上传太方便&#xff01;这些快捷操作你知道吗 你有没有试过——正编辑着一张照片&#xff0c;突然想快速转成卡通风格&#xff0c;结果在各种文件夹里翻找半天&#xff0c;再点开上传窗口、层层点击、等待加载……最后发现&#xff1a;光是上传这一步&#xff0c;就耗掉了…

作者头像 李华
网站建设 2026/3/20 17:47:41

开源轻量大模型怎么选?Qwen3-0.6B部署实操手册

开源轻量大模型怎么选&#xff1f;Qwen3-0.6B部署实操手册 在AI应用快速落地的今天&#xff0c;很多开发者和小团队面临一个现实问题&#xff1a;想用大模型&#xff0c;但GPU资源有限、显存不够、部署太重、响应太慢。这时候&#xff0c;轻量级开源大模型就成了真正的“生产力…

作者头像 李华
网站建设 2026/3/21 13:18:27

微调后如何加载Adapter?Qwen2.5-7B推理切换技巧

微调后如何加载Adapter&#xff1f;Qwen2.5-7B推理切换技巧 在完成一次成功的LoRA微调后&#xff0c;你可能会遇到一个看似简单却常被忽略的问题&#xff1a;训练好的Adapter权重文件&#xff0c;到底该怎么用&#xff1f; 不是直接替换原模型&#xff0c;也不是重新合并全部参…

作者头像 李华