Java多线程入门(上):从零认识线程,三种创建方式与常用方法
Java多线程入门上从零认识线程三种创建方式与常用方法想象一下每年春节你和几百万人在12306上抢票。如果网站只有一个工作人员单线程在处理所有人的请求那画面太美不敢看——你得排到元宵节才能买到票。而多线程就像是同时开了几十个售票窗口大家各抢各的效率直接起飞。这就是多线程的魅力。一、什么是多线程它到底有什么好处通俗地说线程是程序里的一条执行路径。你平时写的代码默认都是在main方法里从上往下执行的这就是单线程。而多线程就是在一个程序里同时跑多条执行路径它们互不干扰或者说看起来互不干扰共同完成复杂的任务。为什么要用多线程提高程序效率把大任务拆成小任务多个线程并行执行减少等待时间提升用户体验比如下载文件时一个线程负责下载一个线程负责更新进度条界面不会卡死充分利用CPU资源现代电脑都是多核CPU单线程只能用一个核多线程才能把所有核心都跑起来。生活例子你去银行办业务。单线程 只有一个柜台开放所有人排队多线程 同时开放多个柜台大家并行办理。12306 抢票就是最经典的例子——如果只有一个线程处理全国人民的请求服务器早炸了。二、创建线程的三种方式Java 中创建线程主要有三种方式我们由浅入深逐个讲解。注意启动线程必须使用start()方法而不是直接调用run()。方式一继承 Thread 类这是最简单粗暴的方式写一个类继承Thread重写run()方法把你要做的事写进去。packageduoxiancheng;/** * 继承 Thread 类创建线程 */classMyThreadextendsThread{Overridepublicvoidrun(){for(inti0;i5;i){System.out.println(子线程执行第 i 次);}}}publicclassThreadDemo1{publicstaticvoidmain(String[]args){// 创建线程对象MyThreadtnewMyThread();// 启动线程注意调用 start()不是 run()t.start();// 主线程的任务for(inti0;i5;i){System.out.println(主线程执行第 i 次);}}}运行结果每次可能不一样因为线程是并发执行的⚠️ 重点start() 和 run() 的区别start()告诉 JVM 开启一个新线程新线程会单独执行run()里的代码这才是真正的多线程。run()如果直接调用run()那就跟调用普通方法一样代码还是在当前线程里顺序执行没有开启新线程。// ❌ 错误示范直接调用 run()相当于还是单线程执行t.run();// ✅ 正确示范调用 start()JVM 会开启新线程执行 run() 里的逻辑t.start();❌ 这种方式的缺点Java 是单继承语言一旦你extends Thread就不能再继承其他类了。这在实际开发中非常不灵活所以这种方式不推荐。方式二实现 Runnable 接口既然继承不灵活那就用实现接口的方式。写一个类实现Runnable接口重写run()方法然后把对象传给Thread的构造器这里有一个容易忽视的点就是Thread类实现了Runnable接口packageduoxiancheng;/** * 实现 Runnable 接口创建线程 */classMyRunnableimplementsRunnable{Overridepublicvoidrun(){for(inti0;i5;i){System.out.println(子线程执行第 i 次);}}}publicclassThreadDemo2{publicstaticvoidmain(String[]args){// 1. 创建 Runnable 任务对象MyRunnabletasknewMyRunnable();// 2. 把任务交给 Thread 线程对象ThreadtnewThread(task);// 3. 启动线程t.start();// 主线程的任务for(inti0;i5;i){System.out.println(主线程执行第 i 次);}}}进阶写法匿名内部类如果你不想专门写一个类可以用匿名内部类简化packageduoxiancheng;publicclassThreadDemo3{publicstaticvoidmain(String[]args){// 使用匿名内部类创建 Runnable 对象ThreadtnewThread(newRunnable(){Overridepublicvoidrun(){for(inti0;i5;i){System.out.println(子线程执行第 i 次);}}});t.start();// 主线程的任务for(inti0;i5;i){System.out.println(主线程执行第 i 次);}}}关键理解Runnable 本质上就是一个任务描述书。Thread 才是真正的工人。你把任务书交给工人工人按照任务书去干活。这种方式解耦了任务和执行者比继承 Thread 灵活得多。❌ 以上两种方法的共同缺点Thread和Runnable的run()方法都没有返回值也不能抛出受检异常。如果你希望线程执行完后返回一个结果这两种方式都做不到。方式三实现 Callable 接口直接创建线程时功能最强Callable 是 JDK 5 引入的可以说是直接创建线程时功能最强的选择。它的call()方法既能返回值也能抛出异常。而且后文我们要讲的线程池接收的主要就是Callable和Runnable类型的任务。不过Callable 不能直接与 Thread 挂钩需要通过FutureTask进行中转。packageduoxiancheng;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.FutureTask;/** * 实现 Callable 接口创建线程 */classMyCallableimplementsCallableString{OverridepublicStringcall()throwsException{intsum0;for(inti1;i100;i){sumi;}return计算完毕1到100的和是sum;}}publicclassThreadDemo4{publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{// 1. 创建 Callable 任务对象MyCallablecallablenewMyCallable();// 2. 把 Callable 封装成 FutureTaskFutureTask 本质上就是一个 RunnableFutureTaskStringfutureTasknewFutureTask(callable);// 3. 把 FutureTask 交给 ThreadThreadtnewThread(futureTask);// 4. 启动线程t.start();// 5. 获取线程执行完毕后的结果如果线程还没执行完这里会阻塞等待StringresultfutureTask.get();System.out.println(result);}}为什么需要 FutureTaskFutureTask本质上是一个Runnable 线程任务对象所以它可以交给Thread去执行。同时它又包装了Callable因此可以通过get()方法获取线程执行完毕后的返回值。你可以把它理解成一个双料间谍对外表现成 Runnable能交给 Thread对内封装了 Callable能拿到返回值。⚠️注意futureTask.get()是一个阻塞方法。如果子线程还没执行完主线程会在这一句一直等直到子线程返回结果。 先别急着兴奋Callable 确实比前两种方式强大但正如后文线程池部分会详细讲到的在实际项目开发中我们很少直接new Thread()而是把 Callable 或 Runnable 任务提交给线程池去执行。现在先掌握它的用法即可。三、线程的六大状态生命周期线程从创建到死亡会经历不同的状态。理解这些状态能帮你更好地排查线程卡死、线程不执行等问题。状态说明NEW新建状态。线程刚被创建还没调用start()。RUNNABLE可运行状态。调用了start()线程正在运行或等待CPU调度。BLOCKED阻塞状态。线程试图获取一个锁但锁被别的线程占用了。WAITING无限等待状态。线程调用了wait()或join()且无超时需要被唤醒。TIMED_WAITING限时等待状态。线程调用了sleep(时间)或join(时间)时间到自动恢复。TERMINATED终止状态。线程执行完毕或异常退出。packageduoxiancheng;publicclassThreadStateDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadtnewThread(()-{try{Thread.sleep(100);// 进入 TIMED_WAITING}catch(InterruptedExceptione){e.printStackTrace();}});System.out.println(新建后t.getState());// NEWt.start();System.out.println(启动后t.getState());// RUNNABLE或 TIMED_WAITINGThread.sleep(10);// 让主线程稍等确保子线程进入 sleepSystem.out.println(子线程睡眠中t.getState());// TIMED_WAITINGt.join();// 等待子线程执行完毕System.out.println(子线程结束后t.getState());// TERMINATED}}重要结论线程进入BLOCKED、WAITING、TIMED_WAITING状态时都会让出 CPU不会一直占着资源。四、线程的常用方法与构造器常用方法方法说明run()线程要执行的逻辑直接调用不会开启新线程。start()启动线程让 JVM 调度执行run()。getName()获取线程名字默认是Thread-0、Thread-1这种格式。setName(String name)给线程起个自定义名字方便排查问题。Thread.currentThread()获取当前正在执行的线程对象。sleep(long millis)让当前线程休眠指定毫秒进入TIMED_WAITING。join()让当前线程等待调用者线程执行完毕再继续执行。常见构造器// 1. 给线程起个名字Threadt1newThread(下载线程-A);// 2. 传入 Runnable 任务Threadt2newThread(newMyRunnable());// 3. 传入 Runnable 任务同时起名字最常用Threadt3newThread(newMyRunnable(),下载线程-B);代码演示packageduoxiancheng;publicclassThreadMethodDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadtnewThread(()-{System.out.println(子线程名字Thread.currentThread().getName());try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(子线程执行完毕);},我的工作线程);t.start();// 主线程等待子线程执行完毕t.join();System.out.println(主线程继续执行);}}写在最后作为初学者你只需要记住这三条核心结论创建线程有三种方式继承 Thread不推荐、实现 Runnable无返回值、实现 Callable有返回值直接创建时功能最强启动线程一定用start()直接调用run()就是普通方法线程有六大状态其中BLOCKED、WAITING、TIMED_WAITING都会让出 CPU。当然光是创建线程还不够。当多个线程同时操作同一份数据时就会引出线程安全问题——这也是中篇要重点讲的线程同步与锁机制。

相关新闻

PyTorch MPS 后端实战:Mac M1 芯片 MNIST 训练 6 倍加速与 Tesla P100 对比

PyTorch MPS 后端实战:Mac M1 芯片 MNIST 训练 6 倍加速与 Tesla P100 对比

PyTorch MPS 后端深度评测:Mac M1 芯片在 MNIST 训练中的性能突破与硬件对比当苹果首次推出 M1 芯片时,整个技术社区都在猜测这款 ARM 架构芯片能否真正胜任专业级计算任务。如今,随着 PyTorch 官方对 MPS(Metal Performance Shad…

2026/7/7 7:03:17阅读更多 →
LED关键参数实战选型指南:5个核心指标决定照明质量与寿命

LED关键参数实战选型指南:5个核心指标决定照明质量与寿命

LED关键参数实战选型指南:5个核心指标决定照明质量与寿命1. 光通量与发光效率:照明效果的经济学光通量(单位:流明,lm)是衡量LED光源总发光量的基础指标。在商业照明项目中,我们曾遇到一个典型案…

2026/7/7 7:03:17阅读更多 →
Token 是怎么来的?

Token 是怎么来的?

很多人第一次看到 Token,会认为:是不是程序员提前规定好的?例如:你好. 编号是:1234其实不然。现代大语言模型中的 Token,大多数都是通过算法自动学习出来的。训练模型之前,工程师会先收集互联网上的海量文本。例如&…

2026/7/7 7:03:17阅读更多 →
AI大模型小白入门指南:从Skill到虚拟员工,一步步掌握AI产品设计核心

AI大模型小白入门指南:从Skill到虚拟员工,一步步掌握AI产品设计核心

本文探讨了企业如何通过AI技术将优秀员工的能力进行留存和复用,提出了从能力单元(Skill)到岗位承接(虚拟员工)的AI产品设计路径。文章详细解析了Skill、专家、专家团、Claw、Agent和虚拟员工等核心概念,并通…

2026/7/7 8:18:24阅读更多 →
杭州吟颂:浙江职称资格评审申报计划发布

杭州吟颂:浙江职称资格评审申报计划发布

1.基本信息 评审计划编号2026-00220评审计划年度2026年度评审计划名称关于开展2026年度衢州市工艺美术专业中、初级专业技术职务任职资格评审申报计划评审委员会名称衢州市工艺美术师职务任职资格评审委员会联系电话0570-8761230计划类型职称评审申报时间个人申报开始时间&…

2026/7/7 8:18:24阅读更多 →
Java毕设选题推荐:基于 SpringBoot 的养老院管理系统的设计与实现 基于 Java 的养老院管理系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

Java毕设选题推荐:基于 SpringBoot 的养老院管理系统的设计与实现 基于 Java 的养老院管理系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/7 8:18:24阅读更多 →
如何快速获取QQ空间历史说说:GetQzonehistory完整指南与实战教程

如何快速获取QQ空间历史说说:GetQzonehistory完整指南与实战教程

如何快速获取QQ空间历史说说:GetQzonehistory完整指南与实战教程 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾试图找回QQ空间中那些被时间淹没的青春记忆&#x…

2026/7/7 8:18:24阅读更多 →
电磁寻迹智能车PCB设计:从5路电感布局到0603/0805封装选择的3个避坑点

电磁寻迹智能车PCB设计:从5路电感布局到0603/0805封装选择的3个避坑点

电磁寻迹智能车PCB设计实战:从电感布局到封装选择的深度解析在智能车竞赛和创客项目中,电磁寻迹方案因其稳定性和适应性广受青睐。然而,许多初学者在PCB设计阶段就会遇到各种"坑",导致后期调试困难甚至需要重新制板。本…

2026/7/7 8:18:24阅读更多 →
Okbiye|告别无效写稿!专属期刊AI写作,精准适配全层级刊物投稿

Okbiye|告别无效写稿!专属期刊AI写作,精准适配全层级刊物投稿

okbiye-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/期刊论文期刊论文 - Okbiye智能写作https://www.okbiye.com/ai/qklw 写期刊论文、投学术刊物,是无数学生和科研工作者的刚需,但也是公认的耗时难题。大部分人写稿翻车、投稿被拒&#…

2026/7/7 8:13:22阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/7 4:43:43阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/7 2:56:31阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/7 1:03:28阅读更多 →
Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

1. 项目概述:Acunetix v24.8 高级版漏洞扫描器深度解析作为一名在网络安全领域摸爬滚打多年的老兵,我深知一款趁手的“兵器”对于安全测试工作意味着什么。今天要聊的,就是Web应用安全测试领域里一个响当当的名字——Acunetix。特别是其v24.8…

2026/7/7 0:02:41阅读更多 →
国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot) 🌐 演示地址:http://ruoyioffice.com | 📦 源码1GitHub:ruoyi-office | 📦 源码2GitCode:ruoyi-o…

2026/7/7 0:02:41阅读更多 →
CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS SSH连接故障排查:从基础检查到深度修复的完整指南引言当你尝试通过Xshell或其他SSH客户端连接CentOS服务器时,突然遭遇"Connection refused"或"Connection timed out"的错误提示,这种经历对任何运维人员或开发者来…

2026/7/7 0:02:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/7 5:11:21阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/7 5:11:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/7 5:11:21阅读更多 →