进程和线程的比较
目录
一、前言
二、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利用率高的排查 三、线程的实现 四、上下文切换 五、总结 一、前言 进程是程序执行相关资源(CPU、内存、磁盘等)分配的最小单元,是一…...

深入理解 Flink(四)Flink Time+WaterMark+Window 深入分析
Flink Window 常见需求背景 需求描述 每隔 5 秒,计算最近 10 秒单词出现的次数 —— 滑动窗口 每隔 5 秒,计算最近 5 秒单词出现的次数 —— 滚动窗口 关于 Flink time 种类 TimeCharacteristic ProcessingTimeIngestionTimeEventTime WindowAssign…...

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

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

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

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

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

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

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

几件奇怪的事产生的疑团
1.记得当年在中国科技大学杨照华给我们上初等数论课(杨是北大毕业,闵嗣鹤教授的关门弟子,后来到华南师大任教),他说过“据华老(华罗庚)讲,希尔伯特最先解决华林问题的论文中用到二十…...

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

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

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

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

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

小程序的完整开发流程?
小程序的完整开发流程可以分为以下几个步骤: 需求分析和设计:明确小程序的功能需求和设计思路,包括页面结构、交互逻辑等。 环境搭建:安装并配置开发工具,如微信开发者工具或其他小程序开发工具。 项目初始化&#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 中,一个 Bean 就是一个类的一个对象实例。 它(Bean)是通过容器来存放和管理整个生命周期的。 最直观的感受就是省去了频繁new的过程,节省了资源的开销。 二、Bean的使用 1、创建Bean 在【gateway/app/Http/Controller】下新建一个名为…...

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

swing快速入门(四十)JList、JComboBox实现列表框
注释很详细,直接上代码 上一篇 新增内容 🧧1.列表的属性设置与选项监听器 🧧2.下拉框的属性设置与选项监听器 🧧3.Box中组件填充情况不符合预期的处理方法 🧧4.LIst向Vector的转化方法 源码: package swing…...

React Native 原生组件回调JS层方法和 JS 层调用原生组件的事件方法
一、原生组件回调 JS 层提供的事件方法 比如 TextInput 组件 onChangeText 属性,输入事件是发生在原生层的但是需要通知 JS 层发生了变化,并执行 JS 层的方法。 1、给原生组件添加一个按钮用于触发原生事件方法 在 XML 中添加一个按钮 为了方便让 Inf…...

Go-安装与基础语法
TOC 1. Go 安装与环境变量 1.1 下载 需要从Go语言的官方网站下载适合你操作系统的Go语言安装包。Go语言支持多种操作系统,包括Windows、Linux和Mac OS。 对于Windows用户,下载.msi文件,然后双击该文件,按照提示进行安装即可。…...

【同济子豪兄斯坦福CS224W中文精讲】NetworkX代码学习笔记
文章目录 安装配置创建图可视化图图数据挖掘参考资料 安装配置 matplotlib中文字体设置 import networkx as nx import matplotlib.pyplot as plt # 魔法指令,设置后在jupyter notebook中绘制的图形会显示在输出单元格中,而不是弹出一个新窗口 %matplo…...

java+ssm+vue代码视频学习讲解
一、ssm 1.项目文件结构 2.数据库连接信息 3.其他配置信息 4.java代码文件目录介绍 5.entity层代码 6.controller,service,dao,entity层之间的关系 7.controller层代码 8.登陆拦截功能实现 AuthorizationInterceptor.java 9.文件上传功能 …...

[计算机提升] 创建FTP共享
4.7 创建FTP共享 4.7.1 FTP介绍 在Windows系统中,FTP共享是一种用于在网络上进行文件传输的标准协议。它可以让用户通过FTP客户端程序访问并下载或上传文件,实现文件共享。 FTP共享的用途非常广泛,例如可以让多个用户共享文件、进行文件备份…...

R语言将list转变为dataframe(常用)
在R语言使用中常常遇到list文件需要转变为dataframe格式文件处理。这是需要写循环来进行转换。IOBR查看其收录的相关基因集(自备)_iobr_deg-CSDN博客 示例文件 list文件: 循环转换为dataframe data <- signature_tme dat <- as.data.frame(t(sapply(data, …...

【JAVA】OPENGL+TIFF格式图片,不同阈值旋转效果
有些科学研究领域会用到一些TIFF格式图片,由于是多张图片相互渐变,看起来比较有意思: import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.*;/*** 可以自已定义日志打印格式…...

Linux系统中使用ln命令创建软连接
大家应该和我一样,第一次听到软连接这个词时感觉好高级啊,但其实也就那么回事,你完全可以将他类比为Windows系统中的快捷方式。 链接只是一个指向,并不是物理移动,类似Windows系统的快捷方式 1.功能和语法 功能&…...

Spark---RDD(Key-Value类型转换算子)
文章目录 1.RDD Key-Value类型1.1 partitionBy1.2 reduceByKey1.3 groupByKeyreduceByKey和groupByKey的区别分区间和分区内 1.4 aggregateByKey获取相同key的value的平均值 1.5 foldByKey1.6 combineByKey1.7 sortByKey1.8 join1.9 leftOuterJoin1.10 cogroup 1.RDD Key-Value…...

后台代码New出来DataGridTextColumn 动态添加到DataGrain 设置 Margin属性
在 WPF 中给 DataGridTextColumn 设置 MarginProperty 可以通过自定义 DataGridTemplateColumn 来实现。以下是一个示例代码: <DataGrid><DataGrid.Columns><DataGridTemplateColumn><DataGridTemplateColumn.CellTemplate><DataTempla…...