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

进程和线程的比较

目录

一、前言

二、Linux查看进程、线程

2.1 Linux最大进程数

2.2 Linux最大线程数

2.3 Linux下CPU利用率高的排查

三、线程的实现

四、上下文切换

五、总结


一、前言

进程是程序执行相关资源(CPU、内存、磁盘等)分配的最小单元,是一系列线程的集合,进程之间相互独立,有自己的内存空间;线程是CPU资源分配的最小单元,线程需要的资源更少,可以看做是一种轻量级的进程,线程会共享进程中的内存,但线程使用独立的栈、程序计数器,线程相互通信更加方便。

在项目开发中,经常会用到线程以及多线程功能来实现异步任务处理等。项目上线之后,如果出现服务CPU高的异常情况,那么这个时候就需要借助Linux(因为一般情况服务都是使用Linux)查看进程、线程来定位最终的问题。

二、Linux查看进程、线程

2.1 Linux最大进程数

Linux中进程可创建的实际值通过进程标识值(process identification value)-PID来标示,可以使用

cat /proc/sys/kernel/pid_max 查看系统中可以创建的进程数实际值

可以使用ulimit命令修改最大限制值,

ulimit -u 1024

 如果要修改kernel.pid_max的值,需要使用

sysctl -w kernel.pid_max=1024

2.2 Linux最大线程数

用ulimit -s可以查看默认的线程栈大小,一般情况下,这个值是8M=8192KB

不过Java程序受JVM堆空间的限制,比如以下代码

public class ThreadExample extends Thread{public static void main(String[] args) {for(int i = 0; i < 100000; i++){ThreadExample myThread = new ThreadExample(i);myThread.start();}}private Integer threadNo;ThreadExample(Integer threadNo){threadNo = threadNo;System.out.println("ThreadNo = " + threadNo);}@Overridepublic void run(){while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

在idea上设置-Xmx1m,启动运行程序,创建出部分线程后,会报OutOfMemoryError错误

2.3 Linux下CPU使用率高的排查

示例代码如下,这段代码可以明显判断出来在while(true){count++;}的地方,会占用很高的CPU使用率,那么如果代码已经上线了,在生产上,我们如何来判断哪里出问题了呢?

public class CpuRatioExample extends Thread{private Integer count = 0;public static void main(String[] args) {CpuRatioExample cpuRatioExample = new CpuRatioExample();cpuRatioExample.start();}@Overridepublic void run(){while(true){count++;}}
}

第一步:运行编译后的class

java CpuRatioExample

程序运行之后,我们发现CPU使用率过高,这个时候,我们需要排查是哪个代码导致的,一般情况生产系统上都会做CPU、磁盘等基础设施的监控。

第二步:CPU使用率过高排查

top 命令查看哪个进程CPU使用率高

使用top命令发现 PID 1822的CPU占用异常,再进一步查找哪个线程导致的,

top -H -p pid 可以查看哪个线程cpu过高

第三步:使用jstack命令保存栈信息

jstack 1822 > 1822.stack

并分析栈信息,查找 1878线程对应的栈信息

 stack信息是以16进制显示的, 所以需要将CPU使用率高的线程1878转换为十六进制 756;定位到在CpuRationExample的17行代码运行,结合源代码,定位了最终问题。 

 

三、线程的实现

3.1 单线程的实现方式

3.1.1 Thread

public class ThreadExample extends Thread{public static void main(String[] args) {for(int i = 0; i < 100000; i++){ThreadExample myThread = new ThreadExample(i);myThread.start();}}private Integer threadNo;ThreadExample(Integer threadNo){threadNo = threadNo;System.out.println("ThreadNo = " + threadNo);}@Overridepublic void run(){while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

这种方式很简单,但是不支持多重继承,所以不能继承其他类。 

3.1.2 Runnable

public class ThreadExample implements Runnable{public static void main(String[] args) {for(int i = 0; i < 100000; i++){ThreadExample myThread = new ThreadExample(i);new Thread(myThread).start();}}private Integer threadNo;ThreadExample(Integer threadNo){threadNo = threadNo;System.out.println("ThreadNo = " + threadNo);}@Overridepublic void run(){while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

 这种方式比继承Thread类更灵活,因为一个类可以实现多个接口。

3.1.3 FetureTask

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class ThreadExample {public static void main(String[] args) {FutureTask<Integer> futureTask = new FutureTask<>(() -> {// 异步执行的任务return 1;});new Thread(futureTask).start();try {// 获取异步执行的结果int result = futureTask.get();System.out.println("result = " + result);} catch (InterruptedException | ExecutionException e) {// 处理异常}}
}

3.2 线程池的实现方式

有关线程池的,后续再详细介绍。

3.2.1 使用Executors类创建线程池

Executors.newFixedThreadPool(int nThreads):创建一个固定大小的线程池。
Executors.newCachedThreadPool():创建一个可以缓存线程的线程池。
Executors.newSingleThreadExecutor():创建一个单线程化的线程池。

3.2.2 使用ThreadPoolExecutor类创建线程池

ThreadPoolExecutor是一个更底层的类,允许开发者更精细地控制线程池的行为,比如:

ThreadPoolExecutor executor = new ThreadPoolExecutor(  5, // corePoolSize  10, // maximumPoolSize  60L, // keepAliveTime  TimeUnit.SECONDS, // unit  new LinkedBlockingQueue<Runnable>() // workQueue  
);

四、上下文切换

多线程和单线程的选择往往取决于具体的应用场景和需求,单线程是一次只做一件事,按照顺序执行,而多线程可以同时处理多个任务,抢占更多的系统资源,但是也会出现上下文切换,有些时候,多线程的性能未必比单线程要好。比如以下这段代码

public class DemoApplication {public static void main(String[] args) {//运行多线程MultiThreadTester test1 = new MultiThreadTester();test1.Start();//运行单线程SerialTester test2 = new SerialTester();test2.Start();}static class MultiThreadTester extends ThreadContextSwitchTester {@Overridepublic void Start() {long start = System.currentTimeMillis();MyRunnable myRunnable1 = new MyRunnable();Thread[] threads = new Thread[3];//创建多个线程for (int i = 0; i < 3; i++) {threads[i] = new Thread(myRunnable1);threads[i].start();}for (int i = 0; i < 3; i++) {try {//等待一起运行完threads[i].join();} catch (InterruptedException e) {e.printStackTrace();}}long end = System.currentTimeMillis();System.out.println("multi thread exce time: " + (end - start) + "ms");System.out.println("counter: " + counter);}// 创建一个实现Runnable的类class MyRunnable implements Runnable {public void run() {while (counter < 100000000) {synchronized (this) {if(counter < 100000000) {increaseCounter();}}}}}}//创建一个单线程static class SerialTester extends ThreadContextSwitchTester{@Overridepublic void Start() {long start = System.currentTimeMillis();for (long i = 0; i < count; i++) {increaseCounter();}long end = System.currentTimeMillis();System.out.println("serial exec time: " + (end - start) + "ms");System.out.println("counter: " + counter);}}//父类static abstract class ThreadContextSwitchTester {public static final int count = 100000000;public volatile int counter = 0;public int getCount() {return this.counter;}public void increaseCounter() {this.counter += 1;}public abstract void Start();}
}

这段代码的测试结果是,单线程的性能高于多线程的性能,其主要原因就是多线程的上下文切换导致性能降低。

如果想要进一步分析上下文切换情况,可以使用vmstat和pidstat分析上下文切换情况。

五、总结

本文介绍了进程和线程的区别以及Java如何开发单线程、多线程;linux下最大进程数、线程数的限制,以及如何通过jstack排查CPU使用率高的问题。后续将专门针对多线程开发进行介绍。

相关文章:

进程和线程的比较

目录 一、前言 二、Linux查看进程、线程 2.1 Linux最大进程数 2.2 Linux最大线程数 2.3 Linux下CPU利用率高的排查 三、线程的实现 四、上下文切换 五、总结 一、前言 进程是程序执行相关资源&#xff08;CPU、内存、磁盘等&#xff09;分配的最小单元&#xff0c;是一…...

深入理解 Flink(四)Flink Time+WaterMark+Window 深入分析

Flink Window 常见需求背景 需求描述 每隔 5 秒&#xff0c;计算最近 10 秒单词出现的次数 —— 滑动窗口 每隔 5 秒&#xff0c;计算最近 5 秒单词出现的次数 —— 滚动窗口 关于 Flink time 种类 TimeCharacteristic ProcessingTimeIngestionTimeEventTime WindowAssign…...

科技创新领航 ,安川运动控制器为工业自动化赋能助力

迈入工业4.0时代&#xff0c;工业自动化的不断发展&#xff0c;让高精度运动控制成为制造业高质量发展的重要技术手段。北京北成新控伺服技术有限公司作为一家集工业自动化产品销售、系统设计、开发、服务于一体的高新技术企业&#xff0c;其引进推出的运动控制产品一直以卓越的…...

图像异或加密及唯密文攻击

异或加密 第一种加密方式为异或加密&#xff0c;异或加密的原理是利用异或的可逆性质&#xff0c;原始图像的像素八位bit分别与伪随机二进制序列异或&#xff0c;得到的图像就为加密图像。如下图对lena图像进行加密。 伪随机序列为一系列二进制代码&#xff0c;它受加密秘钥控…...

React Grid Layout基础使用

摘要 React Grid Layout是一个用于在React应用程序中创建可拖拽和可调整大小的网格布局的库。它提供了一个灵活的网格系统&#xff0c;可以帮助开发人员构建响应式的布局&#xff0c;并支持拖拽、调整大小和动画效果。本文将介绍如何使用React Grid Layout来创建自适应的布局。…...

第11章 1 文件及IO操作

文章目录 文件的概述及基本操作步骤 p151文件的写入操作 p152文件的读取操作及文件复制 p153文件的读取操作文件复制 with语句的使用 p154一维数据和二维数据的存储与读取 p155高维数据的存储和读取 p156os模块中的常用的函数 p157os.path模块中常用的函数 p158 文件的概述及基…...

Tomcat服务实例部署

目录 **Tomcat 由一系列的组件构成&#xff0c;其中核心的组件有三个&#xff1a;** 什么是 servlet&#xff1f; 什么是 JSP? Tomcat 功能组件结构&#xff1a; Container 结构分析&#xff1a; Tomcat 请求过程&#xff1a; ## Tomcat 服务部署 1.关闭防火墙&#xf…...

高精度彩色3D相机:开启崭新的彩色3D成像时代

3D成像的新时代 近年来&#xff0c;机器人技术的快速发展促使对3D相机技术的需求不断增加&#xff0c;原因在于&#xff0c;相机在提高机器人的性能和实现多种功能方面发挥了决定性作用。然而&#xff0c;其中许多应用所需的解决方案更复杂&#xff0c;仅提供环境的深度信息是…...

借助Gitee将typora图片上传CSDN

概述 前面已经发了一个如何借助Github将typora上的图片上传到csdn上&#xff0c;但这有个缺陷&#xff1a;需要科学上网才能加速查看已经上传到github上的图片&#xff0c;否则就会出现已经上传的图片&#xff0c;无法正常查看的问题 如何解决&#xff1f; 那就可以使用Gite…...

几件奇怪的事产生的疑团

1.记得当年在中国科技大学杨照华给我们上初等数论课&#xff08;杨是北大毕业&#xff0c;闵嗣鹤教授的关门弟子&#xff0c;后来到华南师大任教&#xff09;&#xff0c;他说过“据华老&#xff08;华罗庚&#xff09;讲&#xff0c;希尔伯特最先解决华林问题的论文中用到二十…...

陶瓷碗口缺口检测-图像增强

图像增强 在采集图像的过程中&#xff0c;可能会有由于采集图像环境中光源照射不足&#xff0c;导致采集的图像对比度不足&#xff0c;图像视觉效果较暗的情况&#xff0c;可以通过直方图均衡化或者直方图规定化。如图a为原图像对比度低&#xff0c;图c为其直方图&#xff0c;…...

gitee创建远程仓库并克隆远程仓库到电脑

1、首先点加号新建一个仓库 2、输入仓库名&#xff0c;路径会自动填充&#xff0c;填写简单的仓库介绍&#xff0c;先选择私有&#xff0c;在仓库创建之后&#xff0c;可以改为开源 3、打开建好的仓库 4、复制仓库链接 5、打开一个文件夹(想要存储远程仓库的地址)&#xff0c;在…...

3D人体姿态估计(教程+代码)

3D人体姿态估计是指通过计算机视觉和深度学习技术&#xff0c;从图像或视频中推断出人体的三维姿态信息。它是计算机视觉领域的一个重要研究方向&#xff0c;具有广泛的应用潜力&#xff0c;如人机交互、运动分析、虚拟现实、增强现实等。 传统的2D人体姿态估计方法主要关注通…...

Python异步编程|PySimpleGUI界面读取PDF转换Excel

目录 实例要求 原始pdf文件格式 输出xls文件格式 运行界面 完整代码 代码分析 遍历表格 布局界面 控件简介 写入表格 表格排序 事件循环 异步编程 实例要求 使用PySimpleGUI做一个把单位考勤系统导出的pdf文件合并输出Excel的应用&#xff0c;故事出自&#xff1…...

制造领域 基础概念快速入门介绍

1、基本背景知识 本定义结合国家标准文件有所发挥&#xff0c;仅供参考。 产品&#xff1a;是生产企业向用户或市场以商品形式提供的制成品&#xff1b; 成套设备&#xff1a;在生产企业一般不用装配工序连接&#xff0c;但用于完成相互联系的使用功能的两个或两个以上的产…...

小程序的完整开发流程?

小程序的完整开发流程可以分为以下几个步骤&#xff1a; 需求分析和设计&#xff1a;明确小程序的功能需求和设计思路&#xff0c;包括页面结构、交互逻辑等。 环境搭建&#xff1a;安装并配置开发工具&#xff0c;如微信开发者工具或其他小程序开发工具。 项目初始化&#x…...

【LV13 DAY16 轮询与中断】

轮询实现按键实验 #include "exynos_4412.h"int main() {//GPX1_1设置为输入模式//GPX1.CONGPX1.CON & (~ (0XF<<4));while(1){if(!(GPX1.DAT&(1<<1))){printf("key pressed\n");while(!(GPX1.DAT&(1<<1)));}else{}}return…...

Swoft - Bean

一、Bean 在 Swoft 中&#xff0c;一个 Bean 就是一个类的一个对象实例。 它(Bean)是通过容器来存放和管理整个生命周期的。 最直观的感受就是省去了频繁new的过程&#xff0c;节省了资源的开销。 二、Bean的使用 1、创建Bean 在【gateway/app/Http/Controller】下新建一个名为…...

【产品人卫朋】硬件产品经理:从入门到精通

目录 本文目录 1. 前言说明 2. 内容说明 3. 资料包说明 作者简介 本文目录 1. 前言说明 2. 内容说明 3. 资料包说明 1. 前言说明 本篇内容节选自实体书《硬件产品经理&#xff1a;从入门到精通》。 2. 内容说明 鉴于硬件产品的特殊性&#xff0c;不同产品阶段的时间间…...

swing快速入门(四十)JList、JComboBox实现列表框

注释很详细&#xff0c;直接上代码 上一篇 新增内容 &#x1f9e7;1.列表的属性设置与选项监听器 &#x1f9e7;2.下拉框的属性设置与选项监听器 &#x1f9e7;3.Box中组件填充情况不符合预期的处理方法 &#x1f9e7;4.LIst向Vector的转化方法 源码&#xff1a; package swing…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...