新闻详情

新闻详情

首页 / 资讯中心 / 详情

Java多线程编程基础与实战练习

发布时间:2026/11/4 10:43:36来源:尧图网络
Java多线程编程基础与实战练习
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多线程的核心概念。实际开发中建议从简单方案开始逐步引入更复杂的同步机制。多线程编程需要大量实践和经验积累遇到问题时多查阅文档和源码理解底层原理是关键。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/3 7:07:39

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/3 12:09:35

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/3 12:09:38

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/3 12:09:41

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/4 1:25:31

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/4 3:51:11

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉