【Java|多线程与高并发】线程池详解

这篇具有很好参考价值的文章主要介绍了【Java|多线程与高并发】线程池详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


【Java|多线程与高并发】线程池详解

1. 线程池简介

Java线程池是一种用于管理和重用线程的机制,它可以在需要执行任务时,从线程池中获取线程,执行任务,然后将线程放回池中,以便后续使用。线程池可以有效地管理线程的数量,提高程序的性能和资源利用率。

为什么从线程池里面取线程比直接创建线程快呢?

创建线程是要在操作系统内核中完成的,涉及"用户态"到"内核态"切换操作. 这个切换是有一定开销的. 而线程池取线程是纯的用户态实现.

2. 创建线程池

注意这里线程池创建的写法:

ExecutorService executorService = Executors.newCachedThreadPool();

这里并没有new,而是通过Executors的静态方法newCachedThreadPool来创建的,这里涉及到一种设计模式-“工厂模式”

3. 工厂模式简介

工厂模式(Factory Pattern)是一种创建对象的设计模式,它提供了一种封装对象创建过程的方式,使得客户端代码与具体对象的实例化过程解耦。

工厂模式的主要目的是通过一个工厂类来创建对象,而不是直接在客户端代码中使用new关键字来实例化对象。这样可以隐藏具体对象的创建细节,提供更灵活、可扩展的设计。

详细可参考:工厂模式 | 菜鸟教程

4. 线程池的使用

线程池的使用很简单,只需要实现submit方法即可

public class Demo19 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程执行的任务1");
            }
        });
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程执行的任务2");
            }
        });
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程执行的任务3");
            }
        });
    }
}

这里主要是将任务放到线程池中,线程池里的线程就会去执行这些任务

运行结果:

【Java|多线程与高并发】线程池详解

5. 实现线程池

要想实现线程池,要先弄清楚线程池有哪些功能.

一个线程池中可以同时提交N个任务,线程池里有M个线程来执行这N个任务

如何将N个任务分配给M个线程呢?

可以使用生产者-消费者模型解决这个问题.

以下是一个线程池的简易实现:

public class MyThreadPool {
    private BlockingQueue<Runnable> blockingQueue = new public class MyThreadPool {
    private BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>();

    public void submit(Runnable runnable) throws InterruptedException {
        // 将任务添加到阻塞队列中
        blockingQueue.put(runnable);
    }

    public MyThreadPool(int m){
        // 创建m个线程
        for (int i = 0; i < m; i++) {
            Thread t = new Thread(() ->{
                // 让它一直扫描阻塞队列
                while (true) {
                    try {
                        // 取出任务,并执行
                        Runnable runnable = blockingQueue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t.start();
        }
    }
}

测试上述代码:

public class Demo20 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(5);
        for (int i = 0; i < 10; i++) {
            int temp = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("任务"+ temp);
                }
            });
        }
    }
}

运行结果:

【Java|多线程与高并发】线程池详解

不过上述代码中创建的线程数量是"固定"的,可根据需要自行调整

6. ThreadPoolExecutor的构造方法讲解

ThreadPoolExecutor是Java中线程池的一个具体实现类,它实现了ExecutorService接口。ExecutorService是一个高级的线程池管理接口,提供了更多的灵活性和功能。

ThreadPoolExecutor这个类的构造方法比较复杂
【Java|多线程与高并发】线程池详解

参数:

  • corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut

  • maximumPoolSize - 池中允许的最大线程数

  • keepAliveTime - 当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间。

  • unit - keepAliveTime参数的时间单位

  • workQueue - 用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。(自己传入的任务队列,如果传了就用传入的队列.如果不传,就线程池就去创建)

  • threadFactory - 执行程序创建新线程时使用的工厂

  • handler -任务执行被拒绝时使用的处理程序,因为达到线程限制和队列容量

任务执行被拒绝时使用的程序有以下四个:

【Java|多线程与高并发】线程池详解

实际开发中,主要根据需求选择这里的拒绝策略进行处理.

7. 线程池的线程数量,如何确定?

线程池可以自定义线程的数量

那么在实际开发中,线程池的线程数量设置成多少比较合适?

这个问题主要取决于以下几点:

  1. 任务类型:不同类型的任务对线程数量的需求不同。如果是CPU密集型任务,通常线程数量应该与CPU核心数相近,以充分利用CPU资源。如果是IO密集型任务,可以设置较多的线程数量,以便处理并发的IO操作。
  2. 系统资源:需要考虑系统的硬件资源和性能。如果系统资源有限,例如内存、CPU等,线程数量应适当控制,避免过多的线程导致资源竞争和性能下降。
  3. 并发量:需要根据任务的并发量来确定线程数量。如果任务并发量较高,可以增加线程数量以提高任务处理能力。如果任务并发量较低,可以减少线程数量以节省资源。
  4. 响应时间:需要考虑任务的响应时间要求。如果任务需要快速响应,可以增加线程数量以减少等待时间。如果任务的响应时间可以接受较长的延迟,可以减少线程数量以节省资源。
  5. 线程池类型:不同类型的线程池有不同的线程数量限制。例如,FixedThreadPool固定线程池的线程数量是固定的,CachedThreadPool可缓存线程池的线程数量是动态调整的。

这个问题要考虑的因素有很多,最简单的方法就是去测试

将线程分为设置成不同的数量,然后观察系统的性能和任务的执行情况,根据需要逐步调整线程数量,找到最优的配置。

【Java|多线程与高并发】线程池详解

感谢你的观看!希望这篇文章能帮到你!
专栏: 《从零开始的Java学习之旅》在不断更新中,欢迎订阅!
“愿与君共勉,携手共进!”
【Java|多线程与高并发】线程池详解文章来源地址https://www.toymoban.com/news/detail-504473.html

到了这里,关于【Java|多线程与高并发】线程池详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java|多线程与高并发】JUC中常用的类和接口

    JUC是Java并发编程中的一个重要模块,全称为 Java Util Concurrent (Java并发工具包),它提供了一组用于多线程编程的工具类和框架,帮助开发者更方便地编写线程安全的并发代码。 本文主要介绍 Java Util Concurrent 下的一些常用接口和类 Callable接口类似于Runnable. 有一点区别就是

    2024年02月12日
    浏览(33)
  • 【Java|多线程与高并发】设计模式-单例模式(饿汉式,懒汉式和静态内部类)

    设计模式是一种在软件开发中常用的解决复杂问题的方法论。它提供了一套经过验证的解决方案,用于解决特定类型问题的设计和实现。设计模式可以帮助开发人员提高代码的可重用性、可维护性和可扩展性。 设计模式有很多,本文主要介绍单例模式. 单例模式是一种创建型设

    2024年02月11日
    浏览(54)
  • 多线程与高并发--------线程池

    在开发中,为了提升效率的操作,我们需要将一些业务采用多线程的方式去执行。 比如有一个比较大的任务,可以将任务分成几块,分别交给几个线程去执行,最终做一个汇总就可以了。 比如做业务操作时,需要发送短信或者是发送邮件,这种操作也可以基于异步的方式完

    2024年02月13日
    浏览(40)
  • 多线程与高并发——并发编程(4)

    1.1 生产者消费者概念 生产者-消费者是设计模式的一种,让生产者和消费者基于一个容器来解决强耦合的问题。生产者与消费者彼此之间不会直接通讯,而是通过一个容器(队列)进行通讯。 生产者生产完数据后扔到容器中,不用等消费者来处理; 消费者也不需要去找生产

    2024年02月10日
    浏览(47)
  • 多线程与高并发——并发编程(5)

    为什么要使用线程池? 在开发中,为了提升效率,我们需要将一些业务采用多线程的方式去执行。比如,有一个比较大的任务,可以将任务分成几块,分别交给几个线程去执行,最终做一个汇总即可。再比如,做业务操作时,需要发送短信或邮件,这些操作也可以基于异步的

    2024年02月09日
    浏览(44)
  • 多线程与高并发--------阻塞队列

    1.1 生产者消费者概念 生产者消费者是设计模式的一种。让生产者和消费者基于一个容器来解决强耦合问题。 生产者 消费者彼此之间不会直接通讯的,而是通过一个容器(队列)进行通讯。 所以生产者生产完数据后扔到容器中,不通用等待消费者来处理。 消费者不需要去找

    2024年02月13日
    浏览(37)
  • 探索Java并发编程利器:LockSupport,一种高效的线程阻塞与唤醒机制

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 我们继续总结学习 Java基础知识 ,温故知新。 LockSupport 是 Java SE 9 及以上版本中引入的一个线程同步工具类,用

    2024年02月16日
    浏览(53)
  • Java并发编程之线程池详解

    目录 🐳今日良言:不悲伤 不彷徨 有风听风 有雨看雨 🐇一、简介 🐇二、相关代码 🐼1.线程池代码 🐼2.自定义实现线程池 🐇三、ThreadPoolExecutor类 首先来介绍一下什么是线程池,线程池是一种利用池化技术思想来实现的线程管理技术,主要是为了复用线程、便利地管理线程

    2024年02月12日
    浏览(46)
  • 【Java 并发编程】Java 线程本地变量 ThreadLocal 详解

    先一起看一下 ThreadLocal 类的官方解释: 用大白话翻译过来,大体的意思是: ThreadLoal 提供给了 线程局部变量 。同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意: 因为每个 Thread 内有自己的实例副本,且 该副本只能由当前 Thread 使用 。

    2024年02月04日
    浏览(71)
  • Elasticsearch:ESQL 简介 — 一种用于灵活、迭代分析的新查询语言

    作者:Seth Payne 特别声明 :截止撰写该博文,在目前的公开发行版中,该功能还不能公开测试。这个功能将在未来的发行版中发布。 长期以来,Elastic Platform 一直被视为搜索用例和机器生成数据的分析系统。 分析专注于处理摄入的数据,其中重要的思想是如何在 Elasticsearch

    2023年04月23日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包