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

并发编程:Java中的多线程与线程池!

全文目录:

    • 开篇语
      • 线程的基础概念
        • 线程生命周期
        • 线程调度
        • 线程安全
      • 线程池:Executor框架、线程池的管理与调优
        • Executor框架
        • 线程池的管理与调优
      • 并发工具类:ReentrantLock、CountDownLatch、CyclicBarrier等
        • ReentrantLock
        • CountDownLatch
        • CyclicBarrier
      • 小结
    • 文末

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

线程的基础概念

当我们谈到并发编程时,最核心的概念之一便是线程。线程是一条执行路径,在Java中,线程允许你将一个程序分成多个并行执行的任务。Java中多线程的核心作用是提高程序的执行效率,尤其在处理I/O操作、并行计算等场景中具有重要意义。然而,线程的使用并不是那么简单,特别是在资源共享和同步时,可能会导致诸如死锁、竞态条件等问题。因此,理解线程的生命周期、调度以及线程安全机制,是编写高效并发程序的基础。

线程生命周期

在Java中,线程从创建到终止的过程被称为线程生命周期。线程的生命周期包括几个重要的状态,每个状态有其特定的行为和转变过程。下面简要介绍每个线程状态及其转变:

  1. 新建状态(New):当你创建一个线程对象时,线程进入“新建”状态。此时,线程还没有开始执行。

    Thread t = new Thread();
    // 线程t处于New状态
    
  2. 就绪状态(Runnable):当你调用线程的start()方法时,线程进入“就绪”状态,表示线程已经准备好,等待系统分配CPU时间执行。

    t.start();  // 线程进入Runnable状态,等待调度
    
  3. 运行状态(Running):线程获得CPU时间片并开始执行。在Java中,线程可以通过Thread.sleep()等方法主动放弃执行时间片,转入“阻塞”状态。

    public void run() {System.out.println("线程开始执行...");
    }
    
  4. 阻塞状态(Blocked):线程在等待某个资源(例如I/O操作或获取锁)时,会进入“阻塞”状态。阻塞状态的线程会等待直到资源可用或获得锁。

    synchronized (this) {// 当前线程可能被阻塞// 等待锁
    }
    
  5. 终止状态(Terminated):线程执行完毕或者由于异常终止时,进入“终止”状态。线程一旦结束,它就不能再重新启动。

    // 线程执行完毕,进入Terminated状态
    
线程调度

线程调度是指操作系统决定哪个线程获得CPU时间片的过程。在Java中,线程调度依赖于操作系统,但Java也允许我们为线程设置优先级来影响调度的顺序。线程的优先级范围是1到10,其中1表示最低优先级,10表示最高优先级。Java中通过Thread.setPriority()方法来设置线程优先级。

Thread t = new Thread();
t.setPriority(Thread.MAX_PRIORITY);  // 设置最高优先级

需要注意的是,线程优先级并不总是能准确影响线程执行顺序,这取决于底层操作系统的调度策略。

线程安全

多线程编程中的一个核心问题是线程安全。当多个线程并发访问共享资源时,必须确保资源的访问不会导致数据不一致或程序崩溃。常见的线程安全问题包括:

  1. 竞态条件(Race Condition):多个线程并发访问同一资源时,程序的执行结果依赖于线程的执行顺序,导致结果不确定。比如,两个线程同时修改共享变量,可能导致数据丢失或错误。

    int count = 0;
    // 线程1执行 count++
    // 线程2执行 count++
    // 竞态条件发生
    
  2. 死锁(Deadlock):当多个线程互相等待对方释放资源时,形成了死锁,导致程序无法继续执行。

    synchronized (lock1) {synchronized (lock2) {// 代码块}
    }
    synchronized (lock2) {synchronized (lock1) {// 代码块}
    }
    
  3. 资源竞争(Resource Contention):多个线程在没有适当同步的情况下争夺资源,可能导致数据一致性问题。比如在更新数据库记录时,如果没有同步控制,可能导致多个线程同时修改同一数据。

为了解决线程安全问题,Java提供了多种方法,如使用synchronized关键字、ReentrantLock等工具类来进行线程同步。

线程池:Executor框架、线程池的管理与调优

在Java中,线程池是管理线程并发执行的重要工具。使用线程池可以避免频繁创建和销毁线程的开销,提升系统性能,尤其是对于高并发的应用程序来说,线程池是非常必要的。Java提供了Executor框架,用于简化线程池的创建和管理。

Executor框架

Executor框架是Java中用于管理线程池的核心框架。它包含了几个接口和类,用于创建和管理线程池。Executor框架最常用的实现类是ThreadPoolExecutor,它提供了许多灵活的配置选项,能够满足不同场景下的需求。

常见的线程池类型有:

  1. FixedThreadPool:一个固定大小的线程池,适用于负载稳定、任务数目确定的场景。

    ExecutorService executorService = Executors.newFixedThreadPool(10);
    executorService.submit(() -> {System.out.println("Task executed by fixed thread pool.");
    });
    
  2. CachedThreadPool:一个线程池,它会根据任务量动态创建线程,适合任务量非常大,但每个任务执行时间较短的场景。

    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.submit(() -> {System.out.println("Task executed by cached thread pool.");
    });
    
  3. SingleThreadExecutor:一个单线程池,适合顺序执行任务的场景。

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(() -> {System.out.println("Task executed by single thread pool.");
    });
    
线程池的管理与调优

要充分发挥线程池的性能,合理的线程池配置和调优是必不可少的。线程池的主要参数有:

  1. 核心线程数(corePoolSize):线程池中始终保持的线程数。如果线程池中的线程数低于核心线程数,即使没有任务,线程池也会创建新的线程。

  2. 最大线程数(maximumPoolSize):线程池可以创建的最大线程数。当队列满时,线程池会根据配置的最大线程数创建新线程,处理更多的任务。

  3. 空闲线程存活时间(keepAliveTime):线程池中的线程在空闲时保持活跃的时间。超过这个时间的线程会被销毁。

  4. 任务队列(workQueue):存放等待执行任务的队列。可以选择不同类型的队列来管理任务的提交。

通过调整这些参数,可以让线程池适应不同的工作负载,提升并发执行的效率。


并发工具类:ReentrantLock、CountDownLatch、CyclicBarrier等

Java还提供了丰富的并发工具类,帮助我们更高效地进行线程同步和协作。这些工具类可以帮助我们解决一些复杂的同步问题,而不需要过多地依赖synchronized关键字。

ReentrantLock

ReentrantLock是一个显式锁,相较于synchronized,它提供了更灵活的锁操作,如尝试加锁、可中断的加锁、锁的公平性等。它适用于需要精确控制线程同步的场景。

ReentrantLock lock = new ReentrantLock();
lock.lock();  // 获取锁
try {// 执行临界区代码
} finally {lock.unlock();  // 释放锁
}
CountDownLatch

CountDownLatch是一种同步工具,用于让一个线程等待多个线程完成任务。它通过一个计数器来控制,计数器的值会随着每个线程的任务完成而减少,当计数器为0时,等待的线程就可以继续执行。

CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {new Thread(() -> {// 执行任务latch.countDown();  // 任务完成,计数器减1}).start();
}
latch.await();  // 等待计数器为0
System.out.println("All threads finished.");
CyclicBarrier

CyclicBarrier用于在多个线程达到某个共同点时,使得所有线程同步执行。适用于需要多线程分段执行的场景。

CyclicBarrier barrier = new CyclicBarrier(3, () -> {System.out.println("All threads have arrived at the barrier.");
});
for (int i = 0; i < 3; i++) {new Thread(() -> {try {// 执行任务barrier.await();  // 等待其他线程到达屏障} catch (Exception e) {e.printStackTrace();}}).start();
}

小结

在Java的并发编程中,我们涉及了线程生命周期、线程池管理、并发工具类等多个方面。通过合理使用这些技术,我们可以创建高效、线程安全的并发应用程序。然而,线程的使用是非常精细的,必须小心调优和管理,避免常见的并发问题(如死锁、竞态条件等)。希望通过这篇文章,大家能够对Java并发编程有更深入的理解,也能在实际开发中更自如地应用这些技术。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

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

相关文章:

  • 魔方的使用
  • LangGraph 深度解析(二):掌握 LangGraph 函数式 API 的状态化 AI 工作流
  • 每日算法题【二叉树】:堆的实现、堆排序的实现、文件中找TopK
  • [光学原理与应用-338]:ZEMAX - Documents\Zemax\Samples
  • 吴恩达机器学习作业九:kmeans聚类
  • 2025最确定性的答案:AI+IP的结合
  • CNB远程部署和EdgeOne Pages
  • 恶补DSP:3.F28335的ePWM模块
  • Wheat Gene ID Convert Tool 小麦中国春不同参考基因组GeneID转换在线工具
  • TensorFlow 深度学习 | 使用底层 API 实现模型训练(附可视化与 MLP)
  • 「日拱一码」066 深度学习——Transformer
  • ADB常用命令大全
  • Linux中的Shell编程 第一章
  • 第09章 t检验:两独立样本t检验
  • 模拟|双指针
  • 【CUDA进阶】MMA分析Bank Conflict与Swizzle(下)
  • python pyqt5开发DoIP上位机【介绍】
  • 【cancelToken取消重复请求】
  • uniapp开发 移动端使用字符串替换注意事项
  • GEE中上传研究区域范围
  • ModuleNotFoundError: No module named ‘_cffi_backend‘
  • 服务器CPU飙升该如何排查火焰图
  • 互联网医院系统优势介绍
  • Java试题-选择题(22)
  • 诊断通信管理(Diagnostic Communication Management)详解
  • Shell脚本命令扩展
  • Langflow核心技术学习笔记(新)
  • 针对 “TCP 数据传输机制” 的攻击
  • STL中的容器,迭代器
  • DAY 18 推断聚类后簇的类型 - 2025.8.30