初识线程:带你理解程序运行的基本流程

一、基本概念

开发程序是为了解决问题

1.程序

一个存在磁盘中的程序(一份文件 代码文件+数据文件)不能解决问题

2.进程

正在运行中的程序 代码和数据 都在内存中

  • 可以解决问题:通过(代码-计算机指令)调度计算机资源(CPU缓存、RAM磁盘、IOSystem IO操作系统)来解决问题
  • 当一个计算机需要同时运行多个进程时,需要操作系统来帮忙
  • 当一个程序需要同时进行多个任务时,需要使用线程
  • 操作系统分配资源的最小单元

3.线程

  • 一个进程的组成部分,任何一个进程都至少有一个线程
  • 进程也需要操作系统帮忙管理线程
  • CPU分配执行任务的最小单元 就是线程
  • 进程使用多线程的优势是:可以共享数据

二、线程

1.Java中实现线程的方式

(1)继承父类(Thread)

  • 继承:public class MyThread extends Thread{ }
  • 重写方法run: public void run( ){ }
  • 将需要独立放在线程中执行的代码写在run方法中
  • 启动线程:使用MyThread类 创建对象并且调用start方法(不可调用run)

eg.创建继承 Thread 的类

/** * 继承 Thread 类的自定义线程类 */ public class MyThread extends Thread { private String threadName; // 构造方法,可以传入线程名称 public MyThread(String name) { this.threadName = name; } /** * 重写 run 方法,包含线程要执行的代码 * 注意:run() 方法是线程的入口点 */ @Override public void run() { System.out.println(threadName + " 线程开始执行..."); try { // 模拟耗时操作 for (int i = 1; i <= 5; i++) { System.out.println(threadName + " - 执行第 " + i + " 次任务"); // 休眠1秒,模拟任务执行时间 Thread.sleep(1000); // 可以调用其他方法 doSomething(i); } } catch (InterruptedException e) { System.out.println(threadName + " 被中断"); } System.out.println(threadName + " 线程执行完毕"); } /** * 线程中可以执行的其他方法 */ private void doSomething(int count) { System.out.println(threadName + " - 正在处理第" + count + "个数据"); } }

使用 MyThread 创建线程并启动

/** * 主类,演示如何使用 MyThread 创建和启动线程 */ public class ThreadExample { public static void main(String[] args) { System.out.println("主线程开始执行..."); // 示例1: 创建单个线程 System.out.println("=== 示例1: 创建单个线程 ==="); // 第一步: 创建 MyThread 对象 MyThread thread1 = new MyThread("线程A"); // 第二步: 调用 start() 方法启动线程 thread1.start(); // 注意:不要调用 run() 方法 // 验证直接调用 run() 和调用 start() 的区别 System.out.println("\n=== 测试直接调用 run() 方法 ==="); MyThread testThread = new MyThread("测试线程"); // 直接调用 run() 方法(错误示例) System.out.println("直接调用 run() 方法:"); testThread.run(); // 这会在当前线程(主线程)中执行,不会创建新线程 System.out.println("\n=== 测试调用 start() 方法 ==="); MyThread testThread2 = new MyThread("正确线程"); testThread2.start(); // 正确:会在新线程中执行 // 主线程继续执行其他任务 for (int i = 0; i < 3; i++) { System.out.println("主线程执行任务: " + i); try { Thread.sleep(800); // 主线程休眠 } catch (InterruptedException e) { e.printStackTrace(); } } // 示例2: 创建多个线程 System.out.println("\n=== 示例2: 创建多个线程 ==="); MyThread thread2 = new MyThread("线程B"); MyThread thread3 = new MyThread("线程C"); // 启动多个线程 thread2.start(); thread3.start(); // 等待所有线程执行完毕 try { thread1.join(); // 等待线程1结束 thread2.join(); // 等待线程2结束 thread3.join(); // 等待线程3结束 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("所有线程执行完毕,主线程结束"); } }

(2)实现接口(Runnable)

  • 实现接口:public class MyRun implements Runnable{ }
  • 重写run方法
  • 实现线程中的代码
  • 使用MyRun创建一个对象,将这个对象放在一个Thread类对象的构造方法中,使用Thread对象start方法

eg.创建实现 Runnable 接口的类

/** * 实现 Runnable 接口的类 */ public class MyRun implements Runnable { private String threadName; // 构造方法,可以传入线程名称 public MyRun(String name) { this.threadName = name; } /** * 重写 run 方法,包含线程要执行的代码 */ @Override public void run() { try { for (int i = 1; i <= 5; i++) { // 模拟耗时操作 Thread.sleep(1000); // 休眠1秒 // 打印当前线程信息 System.out.println(threadName + " - 正在执行: " + i); // 可以在run方法中调用其他方法 doSomething(i); } } catch (InterruptedException e) { System.out.println(threadName + " 被中断"); } System.out.println(threadName + " 执行完毕"); } /** * 线程中可以执行的其他方法 */ private void doSomething(int count) { System.out.println(threadName + " - 执行第" + count + "次操作"); } }

使用 MyRun 创建线程并启动

/** * 主类,演示如何使用 MyRun 创建和启动线程 */ public class ThreadExample { public static void main(String[] args) { System.out.println("主线程开始执行..."); // 示例1: 创建单个线程 System.out.println("=== 示例1: 创建单个线程 ==="); // 第一步: 创建 MyRun 对象(实现了Runnable接口) MyRun myRun1 = new MyRun("线程A"); // 第二步: 将 MyRun 对象作为参数创建 Thread 对象 Thread thread1 = new Thread(myRun1); // 第三步: 调用 Thread 对象的 start() 方法启动线程 thread1.start(); // 主线程继续执行其他任务 for (int i = 0; i < 3; i++) { System.out.println("主线程执行任务: " + i); try { Thread.sleep(800); // 主线程休眠 } catch (InterruptedException e) { e.printStackTrace(); } } // 示例2: 创建多个线程 System.out.println("\n=== 示例2: 创建多个线程 ==="); MyRun myRun2 = new MyRun("线程B"); MyRun myRun3 = new MyRun("线程C"); Thread thread2 = new Thread(myRun2); Thread thread3 = new Thread(myRun3); // 启动多个线程 thread2.start(); thread3.start(); // 等待所有线程执行完毕 try { thread1.join(); // 等待线程1结束 thread2.join(); // 等待线程2结束 thread3.join(); // 等待线程3结束 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("所有线程执行完毕,主线程结束"); } }

(3)实现Callable接口(最新,复杂)

目前所学知识无法实现,后续学到会补充

tips.同一个thread对象不可调用多次start函数(同一个线程在一个生命周期内(创建-运行-销毁)只能启动一次)

但同一个runnable接口类可以同时被多个thread运行

2.继承父类和实现接口两种创建线程的方式区别?

(1)继承机制

继承 Thread 类

// 继承 Thread 类 public class MyThread extends Thread { @Override public void run() { // 线程代码 } } // 使用 MyThread thread = new MyThread(); thread.start();

实现 Runnable 接口

// 实现 Runnable 接口 public class MyRunnable implements Runnable { @Override public void run() { // 线程代码 } } // 使用 MyRunnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); thread.start();

(2)核心区别对比表

对比点继承 Thread 类实现 Runnable 接口
继承限制占用继承位置(Java单继承)不占用继承位置,可以继承其他类
代码结构线程和任务耦合在一起线程和任务分离,更清晰
资源共享相对复杂方便共享资源(同一个Runnable对象)
扩展性较差更好,更灵活
面向对象不符合"组合优于继承"原则符合面向对象设计原则

(3)实际开发中的选择标准

选择继承 Thread 类的情况:
  1. 需要重写 Thread 类的其他方法(如 interrupt())

  2. 简单的单线程任务

  3. 不需要共享资源

  4. 学习或演示目的

选择实现 Runnable 接口的情况:
  1. 需要继承其他类(Java单继承限制)

  2. 需要多个线程共享资源

  3. 使用线程池管理线程

  4. 代码需要更好的可扩展性

  5. 大多数实际项目场景

在绝大多数情况下,应该优先使用实现 Runnable 接口的方式创建线程。只有在需要重写 Thread 类的特定方法时,才考虑继承 Thread 类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1221319.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

后端开发效率翻倍:IntelliJ IDEA的5个“神级插件

一、GitToolBox&#xff1a;Git协作效率加速器功能概述&#xff1a;增强IDEA原生Git功能&#xff0c;将版本控制操作无缝集成到IDE中&#xff0c;避免频繁切换命令行。 核心作用&#xff1a;实时Blame信息&#xff1a;点击代码行右侧显示最近修改者、提交时间和摘要&#xff0c…

Zookeeper在大数据实时报表系统中的应用

Zookeeper在大数据实时报表系统中的应用 关键词&#xff1a;Zookeeper、大数据、实时报表系统、分布式协调、一致性协议、分布式锁、元数据管理 摘要&#xff1a;本文深入探讨Zookeeper在大数据实时报表系统中的核心应用场景&#xff0c;包括分布式协调、配置管理、集群节点管理…

063.经典搜索,剪枝

include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=25; int n; vectorwords; int cnt[N]; char st; int ans=0; void dfs(string cur){ ans=max(ans,(int)cur.size()); for(int i…

从零开始学大模型核心:向量嵌入技术完全指南

文章全面介绍了向量嵌入技术在大模型中的应用&#xff0c;包括词嵌入、文档嵌入、多模态嵌入等多种类型&#xff0c;以及向量索引、存储优化和相似度计算等关键技术。文章详细阐述了嵌入与向量数据库的协同关系&#xff0c;以及在大规模语义搜索、推荐系统、异常检测和RAG等场景…

CF2029G Balanced Problem

题目大意: 有一个长度为 \(n\) 的数组 \(a\) 和一个长度为 \(n\) 的数组 \(c_{i}\),初始全都为 \(0\),有两种操作,一种是前缀加 \(1\),一种是后缀加 \(1\)。 已经进行了 \(m\) 次操作(已给定),现在对于每个 \(…

【技术干货】大模型记忆机制进化全攻略:从存储到经验的AI认知革命

本文解析了LLM智能体记忆机制的三阶段进化&#xff1a;从基础存储到反思提炼&#xff0c;再到经验抽象。这一进化解决了AI在多步骤任务中的逻辑断裂、无法持续学习等痛点&#xff0c;通过主动探索和跨轨迹抽象等技术突破&#xff0c;使AI从"单次响应工具"升级为"…

1.5万字硬核AI架构指南:从单体智能到系统智能的实战设计

正文开始&#xff1a; 回顾这两年的 AI 发展轨迹&#xff0c;你会发现两条截然不同却又并行不悖的主线&#xff1a; 一条是造脑路线&#xff1a;基础模型层&#xff08;Foundation Models&#xff09;的狂奔&#xff0c;各大厂商拼参数、拼算力&#xff0c;目标是通用人工智能…

双非二程序员的大模型逆袭之路:RAG与Agent技术学习指南

本文探讨双非二本科生在大模型应用开发领域的就业前景&#xff0c;指出尽管学历存在挑战&#xff0c;但行业对RAG和Agent技术人才需求旺盛&#xff0c;更看重实际技术能力而非学历。文章分析了企业招聘要求、薪资前景&#xff0c;并提供了系统学习路径&#xff0c;包括Python编…

大模型应用工程师学习路线:从提示词工程到AI系统构建,年薪50w+技能全攻略_这是一份大模型应用学习路线!(附学习资料)

本文详细介绍了大模型应用工程师的完整学习路线&#xff0c;涵盖提示词工程、检索增强生成(RAG)、模型微调、系统部署及AI项目实践五大核心技术。随着大模型与各行业深度融合&#xff0c;应用工程师年薪可达50w。学习路线从基础到进阶&#xff0c;强调实践落地&#xff0c;帮助…

AARONIA(安诺尼)PBS 1 与 PBS 2 近场探头 —— 精准定位电磁干扰源

AARONIA(安诺尼)PBS 1 与 PBS 2 近场探头 —— 精准定位电磁干扰源的专业工具 在电磁兼容(EMC)预测试、电路调试及故障诊断中,快速锁定近场辐射源是提升产品可靠性的关键一步。AARONIA(安诺尼)推出的 PBS 1 与 …

20260126 之所思 - 人生如梦

20260126 之所思做的好的事:1. 天气寒冷干燥,脖子后面长了两颗痘痘,可能是在发育期,扭动脖子就会很疼,要是放在以前肯定是手痒将其挤掉,然后引发炎症,一发不可收拾。以往身体的疼痛与不适还会引起心情烦躁,干事…

mysql day2

sql 语句简单介绍sql语句执行顺序 FROM/JOIN → WHERE → GROUP BY → HAVING → 窗口函数(OVER) → SELECT → DISTINCT → ORDER BY → LIMIT . . . 简单的用法 1. 数据库操作创建数据库 create database db1; 使用…

YOLOv8改进 - 注意力机制 | SENetV2: 用于通道和全局表示的聚合稠密层,结合SE模块和密集层来增强特征表示

前言 本文介绍了将SENetV2与YOLOv8结合的方法&#xff0c;以提升图像分类性能。SENetV2是结合Squeeze-and-Excitation&#xff08;SE&#xff09;模块和密集层的图像分类模型&#xff0c;引入聚合稠密层用于通道和全局表示。其SE模块重新校准通道特征&#xff0c;密集层优化特…

21点,如何计算胜率高达75%

算法原理低牌&#xff08;2-6&#xff09;&#xff1a;1分低牌&#xff08;2-6&#xff09;在21点中通常对玩家有利&#xff0c;因为它们更可能帮助玩家接近21点&#xff08;如16218&#xff0c;16319等&#xff09;&#xff0c;而不会轻易导致爆牌。因此&#xff0c;当低牌被打…

干瞪眼游戏胜率较高的玩法分析

### **干瞪眼游戏胜率较高的玩法分析**在干瞪眼游戏中&#xff0c;玩家需要通过合理出牌、灵活运用牌型和策略性保留关键牌来提高胜率。以下是胜率较高的玩法策略&#xff1a;---#### **1. ** **炸弹的灵活运用** - **核心作用**&#xff1a;炸弹&#xff08;四张相同牌&#x…

中国船级社信息开发咨询中心 APP开发工程师职位深度解析与技术面试指南

中国船级社信息开发咨询中心 APP开发工程师 职位信息 岗位职责: 1、掌握所参与工作涉及的船检业务以及办公业务; 2、移动应用以及微信小程序的需求调研、分析、文档编制工作; 3、移动应用以及微信小程序的编码开发及单元测试工作; 4、移动应用以及微信小程序使用培训、技术…

北航杭州创新研究院移动客户端/前端开发工程师岗位深度解析与面试指南

北京航空航天大学杭州创新研究院 移动客户端/前端开发工程师 职位信息 有意向人员请前往北航杭研院人才招聘网(杭研院官网→招才引智→人才招聘网)注册,登陆填写信息后投递,每人限报1个岗位。 岗位描述: 1.负责移动端 APP(Android)的设计、开发与维护,了解ios/鸿蒙开发;…

量子科技长三角产业创新中心 AI软件开发工程师岗位深度解析与面试指南

量子科技长三角产业创新中心 AI软件开发工程师 职位信息 岗位职责: 1、参与设计开发AI 软件栈开发,包括架构设计、推理引擎、异构调度、图优化、算子开发、算子分析性能优化、编译器优化、AI工具集等; 2、AI网络算子开发、调试优化、整网性能调优,包括算子融合、高性能算子…

Oracle到YashanDB适配:dbms_obfuscation_toolkit的平滑迁移

我们的文章会在微信公众号IT民工的龙马人生和博客网站 ( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。1.1 前言 在…

vue3 - 01 路由的配置和使用

element-plus 官网组件 https://element-plus.org/zh-CN/component/overview路由的配置和使用 1 安装npm install vue-router@next --save1.1创建相关页面2 配置路由 index.tsimport {createRouter,createWebHistory} …