首页 > 其他分享 >如何根据服务器配置选择默认的线程数量:实战指南

如何根据服务器配置选择默认的线程数量:实战指南

时间:2024-04-01 11:31:50浏览次数:12  
标签:poolName 核心 executor param 线程 默认 new 服务器

在现代软件开发与部署中,合理设置线程数量对于充分发挥服务器性能、提升应用程序响应速度和资源利用率至关重要。本文将深入探讨如何根据服务器配置来选择默认的线程数量,旨在为开发者提供一套科学、实用的决策框架。我们将讨论关键因素、评估方法和最佳实践,帮助您在复杂的工作负载场景中找到理想的线程数设置。

一、理解服务器配置与线程关系

1. 处理器核心数与超线程技术

处理器的核心数是决定线程数量的基础。每个物理核心可以独立执行一个线程。现代处理器往往支持超线程技术,如Intel的Hyper-Threading或AMD的Simultaneous Multi-Threading (SMT),允许一个物理核心同时处理两个逻辑线程。因此,服务器的线程总数通常是其物理核心数乘以超线程系数(通常为2)。
在这里插入图片描述
这个是我电脑的配置是四核的但是它支持超线程所以就是一个物理内核支持两个线程(他这个是支持的最大并行数量)。

2. 其他系统资源

除了处理器外,内存容量、I/O子系统(如磁盘、网络)、以及操作系统对多线程的支持程度等也是影响线程数量选择的重要因素。确保系统资源充足且不会成为瓶颈,才能充分发挥多线程的优势。

二、评估应用程序与工作负载特性

1. 应用程序并行性

了解应用程序是否为多线程优化设计,以及其内部任务的并行化程度。高度并行的应用程序可以从更多的线程中受益,而单线程或弱并行应用可能不需要过多线程。

2. 工作负载类型

  1. CPU密集型:这类应用主要依赖处理器进行计算。线程数通常设置接近或等于物理核心数,以减少上下文切换和缓存争用,提高单线程性能。对于支持超线程且测试显示有性能提升的应用,可以考虑设置为逻辑核心数。
  2. IO密集型:这类应用涉及大量外部设备交互。线程在等待I/O时会被阻塞,设置较多的线程(接近或等于逻辑核心数)有助于在等待期间利用空闲核心,提高整体吞吐量。
  3. 混合型:应对不同类型的负载进行分析,或通过实际测试找出最适线程数。

三、线程等待时间(WT)考量

线程等待时间(WT)是指线程在等待资源(如I/O、锁竞争等)而非执行计算的时间比例。根据公式 线程数 = N(CPU核数) * (1 + WT),WT越高,线程数可设置得更多。通过监测应用性能或参考类似应用的经验数据,可以估计WT以指导线程数设置。

四、最佳实践与调整策略

  1. 初始设置与基准测试
    基于上述因素,初步设定线程数,然后进行基准测试以观察系统性能(如CPU利用率、内存使用、响应时间等)。根据测试结果调整线程数,直至找到性能与资源利用的最佳平衡点。
  2. 动态调整
    对于工作负载波动较大的场景,可以考虑使用动态调整线程数的策略,如基于负载自动调整线程池大小。许多编程语言和框架提供了这样的功能,可根据实时系统指标动态调整线程数量。
  3. 考虑其他优化措施
    除了线程数外,还应关注应用程序的线程亲和性设置、锁优化、异步编程、非阻塞I/O等技术,这些都能影响多线程环境下的性能。

五、线程池配置实例

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

public class ThreadPoolUtil {

    private ThreadPoolUtil() {
        throw new AssertionError("Utility class should not be instantiated");
    }

    /**
     * 创建一个配置全面的线程池。
     *
     * @param poolName          线程池名称,用于识别和日志输出
     * @param corePoolSize      核心线程数
     * @param maxPoolSize       最大线程数
     * @param queueCapacity     队列容量
     * @param keepAliveTime     空闲线程存活时间
     * @param unit              时间单位
     * @param rejectionHandler  拒绝策略
     * @param threadFactory     线程工厂
     * @return                  配置好的线程池
     */
    public static ThreadPoolExecutor createThreadPool(
            String poolName,
            int corePoolSize,
            int maxPoolSize,
            int queueCapacity,
            long keepAliveTime,
            TimeUnit unit,
            RejectedExecutionHandler rejectionHandler,
            ThreadFactory threadFactory) {

        if (queueCapacity < 0 || corePoolSize < 0 || maxPoolSize < 0 || corePoolSize > maxPoolSize) {
            throw new IllegalArgumentException("Invalid thread pool configuration");
        }

        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(queueCapacity);

        ThreadFactory namedThreadFactory = threadFactory != null ?
                threadFactory :
                new NamedThreadFactory(poolName);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                namedThreadFactory,
                rejectionHandler);

        executor.allowCoreThreadTimeOut(true); // 允许核心线程超时

        return executor;
    }

    /**
     * 默认线程工厂,为线程命名以方便识别和日志输出。
     */
    private static class NamedThreadFactory implements ThreadFactory {

        private static final AtomicLong THREAD_COUNTER = new AtomicLong(0);

        private final String poolName;
        private final boolean daemon;

        NamedThreadFactory(String poolName) {
            this(poolName, false);
        }

        NamedThreadFactory(String poolName, boolean daemon) {
            this.poolName = poolName;
            this.daemon = daemon;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, poolName + "-thread-" + THREAD_COUNTER.incrementAndGet());
            t.setDaemon(daemon);
            return t;
        }
    }
}
ThreadPoolExecutor executor = ThreadPoolUtil.createThreadPool(
        "MyThreadPool",
        4,  // 核心线程数
        8,  // 最大线程数
        100, // 队列容量
        60, // 空闲线程存活时间(秒)
        TimeUnit.SECONDS,
        new ThreadPoolExecutor.AbortPolicy(), // 拒绝策略
        null); // 使用默认线程工厂,线程非守护线程

// 使用创建好的线程池执行任务
executor.execute(() -> {
    // 任务逻辑
});

// 在应用关闭时,记得优雅地关闭线程池
executor.shutdown();

标签:poolName,核心,executor,param,线程,默认,new,服务器
From: https://blog.csdn.net/weixin_43828090/article/details/137224060

相关文章

  • 线程池 核心原理
    文章目录线程池核心原理ThreadPoolExecutor主要构造函数:执行任务:关闭线程池:线程池生命周期:Executor框架线程池实战步骤1:创建线程池步骤2:创建任务步骤3:提交任务到线程池步骤4:关闭线程池完整示例线程池核心原理线程池的核心原理是基于“池化”(Pooling)思想,这种思想在......
  • 线程池
    文章目录线程池线程池的优点线程池的组成使用线程池的场景线程池配置什么情况下建议不要使用线程池线程池线程池(ThreadPool)是一种在多线程环境下常用的一种资源管理手段,主要用于优化线程的创建和管理,以提高程序性能和资源利用率。线程池维护一个已经创建的线程的集......
  • 服务器硬件基础知识202404
    服务器硬件基础知识涵盖了服务器的各个关键组件和它们的功能。具体如下:处理器(CPU):是服务器的大脑,负责执行指令和处理数据。在服务器的成本构成中,CPU及其关联的芯片组通常占据大约50%的比例。内存(RAM):是服务器的临时存储设备,用于存放正在运行的程序和数据。内存的容量直接影响......
  • Linux服务器运行jenkins
    环境说明linux系统版本:lsb_release-a  JDK版本:1.8  maven版本:3.9.6  不同的操作系统以及软件版本,可能会遇到不一样的问题,一定要注意版本问题。 .1.jenkins版本选择。官网如下,选择一个长期支持板,会稳定很多,也需要考虑JDK版本的支持。因此自己选择使用2.346......
  • Linux服务器运行tomcat
    环境说明linux系统版本:lsb_release-a  JDK版本:1.8  .1.tomcat下载。官网如下https://tomcat.apache.org/ 获取下载地址https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.100/bin/apache-tomcat-8.5.100.tar.gz使用wget命令下载wgethttps://dlcdn.apache.or......
  • Postfix + Dovecot IMAP 服务器的终极指南,完整支持 SPF、DKIM 和 DMARC,以及多域名设
    邮件服务器配置指南本指南将带您完成Postfix+DovecotIMAP服务器的设置,支持SPF、DKIM和DMARC,还将提供多域名配置的额外指导。在本指南中,domain.com将作为您的根域名,mail.domain.com将作为您邮件服务器的主机名。0x01添加DNS记录在您的域名下添加如下DNS记录:mailI......
  • [网络调试]如何在局域网内搭建自己的NTP服务器
    有时候有些特别的需求,比如我这个局域网内有N多设备需要用到时间同步,但这些设备无法上网,各自的时间不一致很是烦恼,原来windows自己是可以搭建自己的NTP服务器的!以下是我从别人的博客寻找的方法,转载一下:https://blog.csdn.net/hyf_forward/article/details/134570960; 1.搭建环境......
  • Android studio制作的mqtt协议通讯app,可用于搭建的meqx服务器,不可连接阿里云
    首先,在app目录下创建一个libs文件夹,导入相应的MQTT的jar包,然后右击jar包拉到最后找到Add...的一个选项,单击就OK了然后就是添加一些权限添加另一个layout的名字activity_main<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.......
  • 【Linux】认识线程池 AND 手撕线程池(正常版)
    文章目录0.回顾进程池1.计算机层面的池化技术2.线程池预备知识2.1介绍线程池2.2设计线程池的意义是什么?2.3其他知识3.回顾C++类与对象3.1cpp什么情况下成员函数必须是静态的?3.1可变参数列表3.2格式化输出函数3.3预定义符号4.图解线程池运作原理4.0完整代码Makefilelog.......
  • 虚拟线程
    什么是虚拟线程首先,我们需要了解什么是虚拟线程。在平时的开发过程中,我们所使用的多线程往往意味着平台线程。平台线程代表着JVM直接与操作系统交互,创建了一个一个的线程,并且在JVM中还要为这个线程单独开辟内存使用。一般在JVM中创建一个平台线程,开销大约在1M左右。为了避免创建......