1. Java多线程基础练习全解析作为一名Java开发者掌握多线程编程是必备技能。今天我将通过四个典型练习带大家从零开始理解Java多线程的核心机制。这些练习看似简单但涵盖了线程创建、控制、同步等关键知识点是面试和实际开发中经常遇到的场景。2. 练习1创建基础线程2.1 线程创建的两种方式Java中创建线程主要有两种方式继承Thread类实现Runnable接口对于打印1到10数字的练习我们分别用两种方式实现// 方式1继承Thread类 class NumberPrinter extends Thread { Override public void run() { for (int i 1; i 10; i) { System.out.println(i); try { Thread.sleep(1000); // 暂停1秒 } catch (InterruptedException e) { e.printStackTrace(); } } } } // 方式2实现Runnable接口 class NumberPrinterRunnable implements Runnable { Override public void run() { for (int i 1; i 10; i) { System.out.println(i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Main { public static void main(String[] args) { // 方式1使用 new NumberPrinter().start(); // 方式2使用 new Thread(new NumberPrinterRunnable()).start(); } }注意实际开发中更推荐实现Runnable接口的方式因为Java不支持多重继承使用接口更灵活。2.2 线程休眠的注意事项Thread.sleep()方法使用时需要注意必须处理InterruptedException异常sleep()是静态方法作用于当前线程sleep()不会释放锁参数单位是毫秒(ms)3. 练习2线程交替执行3.1 基础实现方案实现Hello和World交替打印的最简单方式是使用sleep控制class HelloPrinter implements Runnable { Override public void run() { while (true) { System.out.println(Hello); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class WorldPrinter implements Runnable { Override public void run() { while (true) { try { Thread.sleep(500); // 延迟500ms启动 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(World); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }3.2 更可靠的同步方案使用sleep控制时序不够可靠更好的方式是使用wait/notify机制class SharedPrinter { private boolean helloPrinted false; public synchronized void printHello() throws InterruptedException { while (helloPrinted) { wait(); } System.out.println(Hello); helloPrinted true; notify(); } public synchronized void printWorld() throws InterruptedException { while (!helloPrinted) { wait(); } System.out.println(World); helloPrinted false; notify(); } } class HelloTask implements Runnable { private SharedPrinter printer; public HelloTask(SharedPrinter printer) { this.printer printer; } Override public void run() { try { while (true) { printer.printHello(); Thread.sleep(500); // 控制速度 } } catch (InterruptedException e) { e.printStackTrace(); } } } class WorldTask implements Runnable { private SharedPrinter printer; public WorldTask(SharedPrinter printer) { this.printer printer; } Override public void run() { try { while (true) { printer.printWorld(); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } }4. 练习3线程计数器4.1 基础实现class NumberedThread extends Thread { private int number; public NumberedThread(int number) { this.number number; } Override public void run() { System.out.println(Thread number is running); } } public class Main { public static void main(String[] args) { for (int i 1; i 5; i) { new NumberedThread(i).start(); } } }4.2 线程ID的注意事项线程ID是JVM分配的long型数字通过Thread.currentThread().getId()获取ID从1开始main线程通常是1线程终止后ID可能被重用5. 练习4奇偶数交替打印5.1 同步锁实现class NumberPrinter { private int number 1; private final int maxNumber; public NumberPrinter(int maxNumber) { this.maxNumber maxNumber; } public synchronized void printOdd() throws InterruptedException { while (number maxNumber) { if (number % 2 1) { System.out.println(Thread.currentThread().getName() : number); number; notify(); } else { wait(); } } } public synchronized void printEven() throws InterruptedException { while (number maxNumber) { if (number % 2 0) { System.out.println(Thread.currentThread().getName() : number); number; notify(); } else { wait(); } } } } public class Main { public static void main(String[] args) { NumberPrinter printer new NumberPrinter(20); Thread oddThread new Thread(() - { try { printer.printOdd(); } catch (InterruptedException e) { e.printStackTrace(); } }, OddThread); Thread evenThread new Thread(() - { try { printer.printEven(); } catch (InterruptedException e) { e.printStackTrace(); } }, EvenThread); oddThread.start(); evenThread.start(); } }5.2 使用条件变量优化import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class AdvancedNumberPrinter { private int number 1; private final int maxNumber; private final Lock lock new ReentrantLock(); private final Condition oddCondition lock.newCondition(); private final Condition evenCondition lock.newCondition(); public AdvancedNumberPrinter(int maxNumber) { this.maxNumber maxNumber; } public void printOdd() throws InterruptedException { lock.lock(); try { while (number maxNumber) { if (number % 2 1) { System.out.println(Thread.currentThread().getName() : number); number; evenCondition.signal(); } else { oddCondition.await(); } } } finally { lock.unlock(); } } public void printEven() throws InterruptedException { lock.lock(); try { while (number maxNumber) { if (number % 2 0) { System.out.println(Thread.currentThread().getName() : number); number; oddCondition.signal(); } else { evenCondition.await(); } } } finally { lock.unlock(); } } }6. 多线程编程常见问题与解决方案6.1 线程安全问题问题现象数据不一致随机出现的错误难以复现的问题解决方案使用synchronized关键字使用Lock接口的实现类使用原子类(AtomicInteger等)使用线程安全集合(ConcurrentHashMap等)6.2 死锁问题典型死锁场景// 线程1 synchronized(resourceA) { synchronized(resourceB) { // 操作 } } // 线程2 synchronized(resourceB) { synchronized(resourceA) { // 操作 } }避免死锁的方法按固定顺序获取锁使用tryLock()尝试获取锁设置锁超时时间使用更高级的并发工具6.3 线程间通信常用方式wait/notify/notifyAllCondition的await/signalBlockingQueueCountDownLatch/CyclicBarrier7. 性能优化建议减少锁粒度只锁必要的代码块使用读写锁ReadWriteLock适用于读多写少场景线程池避免频繁创建销毁线程无锁编程CAS操作替代锁并发容器优先使用ConcurrentHashMap等8. 实际开发经验分享命名规范给线程设置有意义的名字方便调试异常处理线程内部的异常要用try-catch捕获资源释放在finally块中释放锁和资源线程中断正确响应中断请求避免过度同步同步范围过大影响性能// 好的线程命名示例 Thread processorThread new Thread(task, ImageProcessor-Thread);重要提示多线程调试比较困难建议使用日志记录关键步骤可以使用Thread.currentThread().getName()来标识不同线程的输出。9. Java多线程知识体系扩展线程状态NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED线程优先级1-10通常不建议依赖优先级守护线程setDaemon(true)JVM退出时不等待守护线程线程组管理一组线程但现代Java中较少使用ThreadLocal线程局部变量每个线程有独立副本10. 高级主题简介Fork/Join框架适合分治算法CompletableFuture异步编程的强大工具Reactive编程响应式编程模型虚拟线程(Java 19)轻量级线程大幅提升并发能力通过这四个基础练习我们系统性地掌握了Java多线程的核心概念。实际开发中建议从简单方案开始逐步引入更复杂的同步机制。多线程编程需要大量实践和经验积累遇到问题时多查阅文档和源码理解底层原理是关键。
企业数字化 ERP 产品动态
相关推荐
DeskcommCRM私有化部署实战:选型、容器化到数据迁移完整指南 先交代一下背景:这次整理的是DeskcommCRM的完整落地过程。事情起因是有个做B2B外贸的小团队找到我,说他们一直在用共享表格跟客户,结果客户多了以后问题越来越明显:跟单记录对不上、报价历史找不到、业务员离职带走了所有联系方式… · 2026/9/23 9:33:39
Python垃圾分类系统毕设实战:从环境搭建到模型推理全流程 简介:这份资源是面向计算机、通信、人工智能、自动化等专业学生与教师的Python垃圾分类系统毕业设计完整源码包,附带部署指南,适合作为毕业设计、期末课程设计或课程大作业的参考方案,也便于基础较好的学习者在此基础上二次开发、… · 2026/9/23 9:33:33
全栈食谱商城系统设计与实现:Flask+Vue技术解析 ## 1. 项目概述:全栈食谱商城系统设计这个项目是一个典型的全栈Web应用开发案例,整合了Python Flask后端、Vue.js前端和小程序端的家庭食谱解决方案。作为从业十年的全栈开发者,我见过太多食谱类应用要么功能单一,要么架构臃肿。而… · 2026/9/23 9:33:32
Johnny-Five 数字微波传感器接入指南:基于 Sensor.Digital 的移动侦测实战 Johnny-Five 数字微波传感器接入指南:基于 Sensor.Digital 的移动侦测实战 【免费下载链接】johnny-five JavaScript Robotics and IoT programming framework, developed at Bocoup. 项目地址: https://gitcode.com/gh_mirrors/jo/johnny-five
导读
本篇以… · 2026/9/23 10:25:25
加勒比海盗2游戏底层逻辑拆解与面试必问点 加勒比海盗2游戏底层逻辑拆解与面试必问点 刚学完 Python 语法,对着 IDE 敲出 Hello World ,心里美滋滋。结果面试官一问:“做个类似 加勒比海盗2游戏 的实时交互系统,你怎么搭项目?”瞬间大脑空白。这就是典型的… · 2026/9/23 10:25:19
锤子r1完整示例:3步搞定项目搭建,避开官方文档坑 锤子r1完整示例:3步搞定项目搭建,避开官方文档坑 官方文档那一堆参数看得人头皮发麻,根本抓不住重点?别慌。今天直接上 完整示例 ,带你从零把锤子r1这个项目跑起来。咱们不整虚的,只讲怎么在最短时间里,把一个能跑、能用的项目搭出来。… · 2026/9/23 10:25:12
狸窝全能视频转换器性能优化一文搞懂 狸窝全能视频转换器性能优化一文搞懂 看了一堆教程还是不会写项目?别急,今天这篇《狸窝全能视频转换器》性能优化实战,带你从代码层面彻底搞懂视频转码的瓶颈与突破。 一、性能瓶颈:为什么你的转码慢得像蜗牛?… · 2026/9/23 10:25:12
一文搞懂什么与什么 大厂面试突击:Python深拷贝与浅拷贝保姆级教程 官方文档那几行 copy 和 copy.deepcopy 的描述,是不是让你看完云里雾里?很多后端开发在接手老项目时,总被“对象引用”这个坑绊倒,明明改了 A 对象,B… · 2026/9/23 10:25:12
Qwen-Image-2.1生成角色立绘提示词大全:透明背景立绘与三视图(附整合包下载教程) Qwen-Image-2.1生成角色立绘提示词大全:透明背景立绘与三视图(附整合包下载教程)
SEO关键词:Qwen-Image-2.1、Qwen-Image-2.1角色立绘、AI生成角色立绘、透明背景PNG、角色三视图、游戏立绘提示词、AI立绘生成、Qwen Image提示词… · 2026/9/23 10:25:06
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29