当前位置: 首页 > news >正文

JavaSE核心知识点03高级特性03-02(多线程)

🤟致敬读者

  • 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉

📘博主相关

  • 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息

文章目录

    • JavaSE核心知识点03高级特性03-02(多线程)
      • **一、多线程基础概念**
      • **二、Java中创建线程的两种方式**
        • **1. 继承Thread类**
        • **2. 实现Runnable接口(推荐)**
      • **三、线程的生命周期**
      • **四、线程安全与同步**
        • **1. 问题:多个线程共享数据导致竞态条件**
        • **2. 解决方案:synchronized关键字**
        • **3. 使用Lock接口(更灵活)**
        • **4. volatile关键字**
      • **五、线程间通信**
      • **六、线程池(重点掌握)**
        • **1. 为什么使用线程池?**
        • **2. 使用Executors创建线程池**
        • **3. 自定义线程池(推荐)**
      • **七、常见问题与注意事项**
      • **八、实战练习**


📃文章前言

  • 🔷文章均为学习工作中整理的笔记。
  • 🔶如有错误请指正,共同学习进步。

在这里插入图片描述

JavaSE核心知识点03高级特性03-02(多线程)

学习Java多线程是一个循序渐进的过程,下面我会从基础到应用为你详细讲解,并附上代码示例帮助你理解。


一、多线程基础概念

1. 什么是线程?

  • 线程是程序执行的最小单位,一个进程可以包含多个线程,多个线程共享进程的内存资源。
  • 多线程允许程序同时执行多个任务,提高资源利用率和响应速度。

类比:想象一家餐厅,一个厨师(单线程)同时处理多个订单会手忙脚乱,多个厨师(多线程)分工协作效率更高。


二、Java中创建线程的两种方式

1. 继承Thread类
public class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程执行: " + Thread.currentThread().getName());}public static void main(String[] args) {MyThread t1 = new MyThread();t1.start(); // 启动线程,JVM自动调用run()}
}

缺点:Java是单继承,继承Thread后无法继承其他类。

2. 实现Runnable接口(推荐)
public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程执行: " + Thread.currentThread().getName());}public static void main(String[] args) {Thread t2 = new Thread(new MyRunnable());t2.start();}
}

优点:避免单继承限制,适合资源共享(如多个线程操作同一Runnable实例)。


三、线程的生命周期

线程的状态包括:

  1. 新建(New):创建未启动。
  2. 就绪(Runnable):调用start()后,等待CPU调度。
  3. 运行(Running):执行run()方法。
  4. 阻塞(Blocked):等待锁、I/O等资源。
  5. 终止(Terminated)run()执行完毕或异常退出。

四、线程安全与同步

1. 问题:多个线程共享数据导致竞态条件
public class Counter {private int count = 0;public void increment() {count++; // 非原子操作,可能被多个线程同时修改}
}
2. 解决方案:synchronized关键字
  • 同步方法:锁住当前对象实例。
public synchronized void increment() {count++;
}
  • 同步代码块:更细粒度控制。
public void increment() {synchronized(this) {count++;}
}
3. 使用Lock接口(更灵活)
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Counter {private int count = 0;private Lock lock = new ReentrantLock();public void increment() {lock.lock();try {count++;} finally {lock.unlock(); // 确保释放锁}}
}
4. volatile关键字
  • 保证变量可见性,但不保证原子性。
private volatile boolean flag = false;

五、线程间通信

使用wait()notify()notifyAll()实现线程协作(必须在同步块内调用)。

public class ProducerConsumer {private Queue<Integer> queue = new LinkedList<>();private int capacity = 5;public synchronized void produce(int item) throws InterruptedException {while (queue.size() == capacity) {wait(); // 队列满,等待}queue.add(item);notifyAll(); // 唤醒消费者}public synchronized int consume() throws InterruptedException {while (queue.isEmpty()) {wait(); // 队列空,等待}int item = queue.poll();notifyAll(); // 唤醒生产者return item;}
}

六、线程池(重点掌握)

1. 为什么使用线程池?
  • 避免频繁创建/销毁线程的开销。
  • 控制并发数量,防止资源耗尽。
2. 使用Executors创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo {public static void main(String[] args) {ExecutorService pool = Executors.newFixedThreadPool(3);for (int i = 0; i < 10; i++) {pool.execute(() -> {System.out.println(Thread.currentThread().getName() + " 执行任务");});}pool.shutdown(); // 关闭线程池}
}
3. 自定义线程池(推荐)
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;ThreadPoolExecutor executor = new ThreadPoolExecutor(5, // 核心线程数10, // 最大线程数60L, TimeUnit.SECONDS, // 空闲线程存活时间new LinkedBlockingQueue<>(100) // 任务队列
);

七、常见问题与注意事项

  1. 死锁:多个线程互相等待对方释放锁。

    • 避免方法:按固定顺序获取锁,使用超时机制(tryLock)。
  2. 线程泄漏:线程未正确关闭导致资源耗尽。

    • 解决:使用try-finally确保资源释放。
  3. 避免使用已废弃方法

    • stop():强制终止线程,可能导致数据不一致。
    • 改用标志位控制线程退出:
    public class SafeStop implements Runnable {private volatile boolean running = true;public void stop() {running = false;}@Overridepublic void run() {while (running) {// 执行任务}}
    }
    

八、实战练习

题目:模拟10个窗口卖100张票(线程安全)。

public class TicketSales implements Runnable {private int tickets = 100;private final Object lock = new Object();@Overridepublic void run() {while (true) {synchronized (lock) {if (tickets <= 0) break;System.out.println(Thread.currentThread().getName() + " 卖出第 " + tickets-- + " 张票");}try {Thread.sleep(100); // 模拟操作耗时} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {TicketSales task = new TicketSales();for (int i = 0; i < 10; i++) {new Thread(task, "窗口" + (i+1)).start();}}
}

通过以上内容,你应该对Java多线程有了全面的认识。学习时建议多写代码调试,观察不同情况下的输出,逐步理解线程的行为。遇到问题可以查阅Java官方文档或可靠的教程资源。



📜文末寄语

  • 🟠关注我,获取更多内容。
  • 🟡技术动态、实战教程、问题解决方案等内容持续更新中。
  • 🟢《全栈知识库》技术交流和分享社区,集结全栈各领域开发者,期待你的加入。
  • 🔵​加入开发者的《专属社群》,分享交流,技术之路不再孤独,一起变强。
  • 🟣点击下方名片获取更多内容🍭🍭🍭👇

http://www.xdnf.cn/news/619903.html

相关文章:

  • C++构造和折构函数详解,超详细!
  • NC IntellisysIQ QP、QPA和QPD QP3 Slave buried slave ON RS232 等通讯接口针脚定义
  • LoRA(Low-Rank Adaptation)
  • ISO 26262-5 评估硬件架构度量值
  • 文章记单词 | 第108篇(六级)
  • 单目视觉测量及双目视觉测量
  • 【GPU并行计算】不同设备上的GPU性能分析
  • 使用arXiv.org上的资源进行学术研究
  • 【agent】一个智能助手agent
  • PCIe学习笔记(3)链路初始化和训练
  • TCP为什么是三次握手,而不是二次?
  • JavaScript 语句标识符详解
  • 肝了三个月的Kaggle比赛学习路径,他来了。
  • 实用蓝牙耳机哪款好?先做好使用场景分析!
  • hysAnalyser特色的TS流编辑、剪辑和转存MP4功能说明
  • 系统架构设计师脑图
  • 未授权访问漏洞利用链实战总结
  • List转字符串去除[]和空格
  • Python基础知识(IO编程)
  • Python 项目中安装 OpenAI 库的详细指南
  • macOs系统M1芯片执行source ~/.zshrc报错503
  • 计算机系统结构 -第三章:指令集并行-2
  • 园区/小区执法仪部署指南:ZeroNews低成本+高带宽方案”
  • Linux入门(部分基础相关知识+常用命令+权限)
  • Baklib内容中台的AI技术支撑是什么?
  • 通过contenteditable实现仿豆包智能输入框
  • 解决PLSQL工具连接Oracle后无法使用ODBC导入器问题
  • 第三章、DQN(Deep Q-Network)
  • 【AS32X601驱动系列教程】PLIC_中断应用详解
  • PADS LAYOUT添加GND过孔