单体应用提高性能和高并发处理-合理使用多核处理
合理使用多核处理能力是提升单体应用性能和处理高并发能力的重要手段。以下是关于如何合理利用多核处理器的详细讲解,包括多线程编程、线程池的使用、并行计算、以及如何避免常见的性能陷阱。
1. 多线程编程
多线程编程是利用多核处理器的直接方式。每个线程可以在不同的核心上并行执行,从而提高应用程序的执行效率。
知识点
- 线程模型:Java中,线程通过
Thread
类或实现Runnable
接口来创建。通过启动多个线程,应用程序可以在多个核心上并行运行。 - CPU密集型 vs I/O密集型任务:对于CPU密集型任务(如计算密集型操作),应该尽可能充分利用CPU核心。对于I/O密集型任务,线程的数量可以适度增加,以在等待I/O操作时切换到其他任务。
实例:
public class MultiThreadExample {public static void main(String[] args) {int numThreads = Runtime.getRuntime().availableProcessors(); // 获取可用的核心数for (int i = 0; i < numThreads; i++) {new Thread(new Task()).start(); // 启动多个线程}}
}class Task implements Runnable {@Overridepublic void run() {// 模拟CPU密集型任务long sum = 0;for (int i = 0; i < 1000000000; i++) {sum += i;}System.out.println(Thread.currentThread().getName() + " 完成任务,结果: " + sum);}
}
在这个例子中,根据可用的CPU核心数创建了多个线程来执行任务。每个线程都可以在不同的核心上运行,从而提高并行计算能力。
2. 使用线程池(Thread Pool)
线程池管理一组可重用的线程,避免频繁创建和销毁线程的开销,适合处理大量并发任务。
知识点
- 固定大小线程池(Fixed Thread Pool):创建一个固定数量的线程池,适合已知数量的并发任务。
- 缓存线程池(Cached Thread Pool):根据需求动态调整线程池大小,适合任务数量不确定的场景。
- Fork/Join框架:适用于递归分治算法,在多核环境下进行高效的并行计算。
实例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {int numThreads = Runtime.getRuntime().availableProcessors();ExecutorService executor = Executors.newFixedThreadPool(numThreads); // 创建固定大小的线程池for (int i = 0; i < numThreads; i++) {executor.submit(new Task()); // 提交任务到线程池}executor.shutdown(); // 关闭线程池}
}class Task implements Runnable {@Overridepublic void run() {long sum = 0;for (int i = 0; i < 1000000000; i++) {sum += i;}System.out.println(Thread.currentThread().getName() + " 完成任务,结果: " + sum);}
}
通过使用线程池,避免了频繁创建和销毁线程的开销,提高了资源的利用率。
3. 并行计算(Parallel Computing)
并行计算是将一个大任务分解为多个子任务,并行在多个核心上执行。Java提供了Fork/Join
框架来简化并行任务的管理。
知识点
- Fork/Join框架:用于将任务分解(Fork)成更小的子任务,然后并行执行,并在所有子任务完成后将结果合并(Join)。
RecursiveTask
:适用于需要返回结果的并行任务。RecursiveAction
:适用于不需要返回结果的并行任务。
实例:
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;public class ParallelExample extends RecursiveTask<Long> {private static final int THRESHOLD = 10000;private long start;private long end;public ParallelExample(long start, long end) {this.start = start;this.end = end;}@Overrideprotected Long compute() {if (end - start <= THRESHOLD) {long sum = 0;for (long i = start; i <= end; i++) {sum += i;}return sum;} else {long mid = (start + end) / 2;ParallelExample leftTask = new ParallelExample(start, mid);ParallelExample rightTask = new ParallelExample(mid + 1, end);leftTask.fork(); // 异步执行左边任务long rightResult = rightTask.compute(); // 同步执行右边任务long leftResult = leftTask.join(); // 获取左边任务结果return leftResult + rightResult;}}public static void main(String[] args) {ForkJoinPool forkJoinPool = new ForkJoinPool();ParallelExample task = new ParallelExample(1, 100000000L);long result = forkJoinPool.invoke(task);System.out.println("并行计算结果: " + result);}
}
Fork/Join
框架将大任务分解为多个子任务并行执行,从而充分利用多核处理能力。
4. 合理设置线程数
合理设置线程数是多核处理的关键。过多的线程会导致上下文切换开销过大,过少的线程则不能充分利用CPU。
知识点
- CPU密集型任务:通常线程数设置为核心数,最大化利用每个核心。
- I/O密集型任务:线程数可以大于核心数,以在等待I/O操作时进行线程切换。
- 自适应线程池:可以根据系统负载动态调整线程池的大小。
实例:
public class OptimalThreadNumberExample {public static void main(String[] args) {int numThreads = Runtime.getRuntime().availableProcessors();System.out.println("推荐线程数(CPU密集型任务): " + numThreads);int ioBoundThreads = numThreads * 2; // I/O密集型任务时,线程数可以设置为核心数的2倍System.out.println("推荐线程数(I/O密集型任务): " + ioBoundThreads);}
}
此代码展示了根据任务类型推荐的线程数设置,帮助在不同场景下合理利用多核资源。
5. 避免共享资源竞争
多线程编程中,避免不同线程之间的资源争用,可以减少锁竞争,从而提高性能。
知识点
- 线程局部变量(ThreadLocal):为每个线程分配独立的变量,避免资源共享。
- 细粒度锁:尽量缩小锁的范围和粒度,减少线程竞争的机会。
实例:
public class ThreadLocalExample {private static ThreadLocal<Integer> threadLocalCounter = ThreadLocal.withInitial(() -> 0);public static void main(String[] args) {int numThreads = Runtime.getRuntime().availableProcessors();for (int i = 0; i < numThreads; i++) {new Thread(() -> {int counter = threadLocalCounter.get();counter++;threadLocalCounter.set(counter);System.out.println(Thread.currentThread().getName() + " 计数器值: " + threadLocalCounter.get());}).start();}}
}
使用ThreadLocal
,每个线程都有独立的计数器,避免了对共享资源的竞争。
总结
合理使用多核处理能力可以显著提高单体应用的性能和高并发处理能力。以下是关键点:
- 多线程编程:利用多线程并行处理任务,充分利用多核资源。
- 线程池:使用线程池管理线程,减少创建和销毁线程的开销。
- 并行计算:将任务分解为子任务并行执行,使用
Fork/Join
框架优化复杂计算。 - 合理设置线程数:根据任务类型设置合适的线程数,避免上下文切换和资源浪费。
- 避免共享资源竞争:通过
ThreadLocal
和细粒度锁等技术减少线程间的资源争用。
通过这些策略,可以充分发挥多核处理器的优势,提升单体应用在高并发环境下的性能。
相关文章:
单体应用提高性能和高并发处理-合理使用多核处理
合理使用多核处理能力是提升单体应用性能和处理高并发能力的重要手段。以下是关于如何合理利用多核处理器的详细讲解,包括多线程编程、线程池的使用、并行计算、以及如何避免常见的性能陷阱。 1. 多线程编程 多线程编程是利用多核处理器的直接方式。每个线程可以在…...

基于STM32/GD32的双CAN、一路485开发板
双CAN开发板 双CAN、一路485开发板的设计开发板配置器件选型CAN设计硬件设计软件设计 485设计硬件设计软件设计 其他设计LED硬件按键硬件 PCB板子和实物图开发板测试视频其他资料 双CAN、一路485开发板的设计 最近工作经常会出现一些小问题。就想设计一款带CAN的开发板用来测试…...

快排/堆排/归并/冒泡/
常见的内排序算法 插入排序 直接插入排序 原理:相当于扑克牌变成有序,先拿第一张,把他调节成有序,再拿第二张,与第一张相比找到第二张的位置,再继续拿第三张,以此类推。 void InsertSort(in…...
React基础教程(08):state体验
文章目录 7、state再体验7.1 异步更新状态7.2 同步更新状态方式17.3 同步更新状态方式27.4 betterScroll7.5 列表案例7、state再体验 7.1 异步更新状态 完整代码 import React from "react";export default class App extends React.Component{state = {count:1,}…...

Win10 创建新的桌面2,并实现桌面切换
1. Win10 创建新的桌面2 Win - Tab 2. Win10 桌面切换 Ctrl - Win - ←/→ 我们下期见,拜拜!...

MySQL数据库介绍及基础操作
目录: 一.数据库介绍 二.数据库分类 三. 数据库的操作 四. 常用数据类型 五. 表的操作 一.数据库介绍 1.文件保存数据有以下几个缺点: 1.1文件的安全性问题 1.2文件不利于数据查询和管理 1.3文件不利于存储海量数据 1.4文件在程序中控制不方便 为了解决上述问题&…...

【C语言篇】C语言常考及易错题整理DAY2
文章目录 C语言常考及易错题整理选择题编程题至少是其他数字两倍的最大数两个数组的交集图片整理寻找数组的中心下标多数元素除自身以外数组的乘积不使用加减乘除求两个数的加法 C语言常考及易错题整理 选择题 下列 for 循环的次数为( ) for(int i 0…...

javase入门
最近在学习大数据,学到flume拦截器的时候发现自定义拦截器需要使用java编写,现在开始学一些java入门的东西. 一. java相关组成 path环境变量: 环境变量用于记住程序路径,方便在命令行窗口任意目录启动程序. 二 java中的变量 变量要先定义在使用. int age 15 定义变量要定义其…...
Wireshark显示过滤器大全:快速定位网络流量中的关键数据包
文章目录 一、简介二、wireshark中的逻辑运算符三、过滤示例集合3.1 过滤指定日期和时间3.2 过滤指定协议3.2.1 例:仅显示SMTP(端口 25)和ICMP流量:3.2.2 例如:Windows 客户端 - DC 交换 3.3 过滤指定网段(…...
OOP笔记4----抽象类、接口、枚举
抽象类 简介 父类可以封装不同子类的共同特征或者共同行为.而有的时候,父类中封装的方法无法具体完成子类中需要的逻辑,因此我们可以将此方法设计成抽象方法,即使用关键字abstract进行修饰。而有抽象方法的类,也必须使用abstract…...

MySQL面试题全解析:准备面试所需的关键知识点和实战经验
MySQL有哪几种数据存储引擎?有什么区别? MySQL支持多种数据存储引擎,其中最常见的是MyISAM和InnoDB引擎。可以通过使用"show engines"命令查看MySQL支持的存储引擎。 存储方式:MyISAM引擎将数据和索引分别存储在两个不…...

01_Electron 跨平台桌面应用开发介绍
Electron 跨平台桌面应用开发介绍 一、Electron 的介绍二、关于 NW.js 和 Electron 介绍三、搭建 Electron 的环境1、准备工作:2、安装 electron 环境3、查看 electron 的版本,electron -v 一、Electron 的介绍 Electron 是由 Github 开发的一个跨平台的…...

【C语言-扫雷游戏】mineweeper【未完成】
编程小白如何成为大神?大学新生的最佳入门攻略 编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。如何选择适合自己的编程语言?如何制定有效的学习计划?如何避免常见的学习陷阱&…...

psychopy stroop 实验设计
斯特鲁stroop实验就是色词一致/不一致实验。 设计步骤如下: 1. 先去设置中将Input改为PsychToolbox, 2. 然后左上角File-New新建一个 3. 右键trial,rename改名 改成自己想要的名字即可,比如欢迎界面welcome。 4. 接下来添加提示语…...
c++精品小游戏(无错畅玩版)
一、俄罗斯方块 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <windows.h>#ifdef _MSC_VER // M$的编译器要给予特殊照顾 #if _MSC_VER < 1200 // VC6及以下版本 #err…...

应急响应-主机安全之系统及进程排查相关命令(Linux操作系统-初级篇)
目录 概述lscpu-显示有关CPU架构的信息uname-查看系统信息lsmod-输出加载的所有模块lastb-输出最后登录失败的用户last-展示用户最近登录信息lastlog-展示所有用户最后的登录时间systemctl-系统服务,开机自启排查crontab-计划任务选项 history-查看历史命令选项常用…...

java中RSA分段加解密及Data must not be longer than异常处理
谈到RSA非对称加密,作为开发的我们第一想到的是安全,几乎不会被破解,以及公钥加密,私钥解密这些。在Java代码中,我们常使用一些现成的工具类如hutool中提供的工具类、网上在线的或者博客上的RSAUtils工具类来实现公钥私…...

MySQL数据分析进阶(十二)设计数据库——PART3
※食用指南:文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记,笔记整理比较粗糙,主要目的自存为主,记录完整的学习过程。(图片超级多,慎看!) 【中字】SQL进阶教程 | 史上最易懂S…...

Kubernetes-1.22.0 可视化部署
目录 Kubeadm方式部署3master,2work集群(Kubernetes-1.22.0)-CSDN博客 1. 官方Dashboard 2. Kuboard 部署 3. Rainbond 部署 4. Kubesphere 部署 1. 官方Dashboard kubectl apply -f https://kuboard.cn/install-script/k8s-dashboard/v2…...
在 vue3 中动态路由问题记录
第一种 如果这样子的话需要加上 /* vite-ignore / ,但是在这样用这行部署服务器上跳转会有问题 component: () > import(/ vite-ignore */ ../views/ e.component .vue) 第二种 // 解决跳转问题const modeules imporet.meta.glob(/views/**/**.vue)component: modules…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...