时间:2022-12-26 17:17编辑:九州下载来源:www.wzjsgs.com
一 cpu个数、核数、线程数的关系
cpu个数:是指物理上,也及硬件上的核心数;
核数:是逻辑上的,简单理解为逻辑上模拟出的核心数;一个CPU核心数模拟出2线程的CPU
线程数:是同一时刻设备能并行执行的程序个数,线程数=cpu个数 * 核数,及程数=cpu个数(2) * 核数(2)=4
Windows: wmic 然后 物理CPU数 “cpu get NumberOfCores”, CPU核心数 “cpu get NumberOfLogicalProcessors”
Linux:
查看CPU个数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
查看核数 cat /proc/cpuinfo| grep "cpu cores"| uniq
二 cpu线程数和Java多线程
(1) 线程是CPU级别的,单个线程同时只能在单个cpu线程中执行
(2) Java多线程并不是由于cpu线程数为多个才称为多线程,当Java线程数大于cpu线程数,操作系统使用时间片机制,采用线程调度算法,频繁的进行线程切换。
(3) 线程是操作系统最小的调度单位,进程是资源(比如:内存)分配的最小单位
(4)Java中的所有线程在JVM进程中,CPU调度的是进程中的线程
线程的调度是指按照特定的机制为多个线程分配CPU的使用权。有两种调度模型:分时调度模型和抢占式调度模型
分时调度模型是指让所有线程轮流获得CPU的使用权,并且平均分配每个线程占用CPU的时间片。
Java虚拟机采用抢占式调度模型,是指优先让可运行池中处于就绪态的线程中优先级高的占用CPU,如果可运行池中线程的优先级相同,那么就随机选择一个线程,使其占用CPU,处于运行状态的线程会一直执行,直至它不得不放弃CPU,一个线程会因为以下原因放弃CPU:
(1)Java虚拟机让当前线程暂时放弃CPU,转到就绪态,使其他线程获得运行机会
(2)当前线程因为某些原因而处于阻塞状态
(3)线程运行结束
Java线程让步:
3. Thread.yield()方法
就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行(根据CPU的调度),并不是单纯的让给其他线程。
4.等待其他线程结束:join()
当前运行的线程可以调用另一个线程的join()方法,当前运行的线程将转到阻塞状态,直至另一个线程运行结束,它才会恢复运行(阻塞恢复到就绪)
就绪:线程分配了CPU以外的全部资源,等待获得CPU调度 执行:线程获得CPU,正在执行 阻塞:线程由于发生I/O或者其他的操作导致无法继续执行,就放弃处理机,转入线程就绪队列 挂起:由于终端请求,操作系统的要求等原因,导致挂起。
利用linux系统自己的线程切换机制,利用pthread库自带的线程亲和性设置函数,来设置线程在某个核心上跑这个程序需要在程序内部实现
PIPE和FIFO用来实现进程间相互发送非常短小的、频率很高的消息;
这两种方式通常适用于两个进程间的通信。
共享内存用来实现进程间共享的、非常庞大的、读写操作频率很高的数据(配合信号量使用);
这种方式通常适用于多进程间通信。
其他考虑用socket。这里的“其他情况”,其实是今天主要会碰到的情况:
分布式开发。
在多进程、多线程、多模块所构成的今天最常见的分布式系统开发中,
socket是第一选择
。
消息队列,现在建议不要使用了 ---- 因为找不到使用它们的理由。
在实际中,我个人感觉,PIPE和FIFO可以偶尔使用下,共享内存都用的不多了。在效率上说,socket有包装数据和解包数据的过程,所以理论上来说socket是没有PIPE/FIFO快,不过现在计算机上真心不计较这么一点点速度损失的。你费劲纠结半天,不如我把socket设计好了,多插一块CPU来得更划算。
另外,进程间通信的数据一般来说我们都会存入数据库的,这样万一某个进程突然死掉或者整个服务器死了,也不至于丢失重要数据、便于回滚到之前的状态。从这个角度考虑,适用共享内存的情况也更少了,所以socket使用得更多。
再多说一点关于共享内存的:共享内存的效率确实高,但它的重点在“共享”二字上。如果的确有好些进程共享一大块数据(如果把每个进程都看做是类的对象的话,那么共享数据就是这个类的static数据成员),那么共享内存就是一个不二的选择了。但是在面向对象的今天,我们更多的时候是多线程+锁+线程间共享数据。因此共享进程在今天使用的也越来越少了。
不过,在面对一些极度追求效率的需求时,共享内存就会成为唯一的选择,比如高频交易系统。除此以外,一般是不需要特意使用共享内存的。
另外,
PIPE和共享内存是不能跨LAN的
(FIFO可以但FIFO只能用于两个进程通信)
。
如果你的分布式系统随着需求的增加而越来越大所以你想把不同的模块放在不同机器上而你之前开发的时候用了PIPE或者共享内存,那么你将不得不对代码进行大幅修改......同时,即使FIFO可以跨越LAN,其代码的可读性、易操作性和可移植性、适应性也远没有socket大。这也就是为什么一开始说socket是第一选择的原因。
最后还有个信号简单说一下。
请注意,是信号,不是信号量。
信号量是用于同步线程间的对象的使用的(建议题主看我的答案,自认为比较通俗易懂:
semaphore和mutex的区别? - Linux - 知乎
)。
信号也是进程间通信的一种方式。比如在Linux系统下,一个进程正在执行时,你用键盘按Ctrl+c,就是给这个进程发送了一个信号。进程在捕捉到这个信号后会做相应的动作。
虽然信号是可以自定义的,但这并不能改变信号的局限性:
不能跨LAN、信息量极其有限
。
在现代的分布式系统中,通常都是
消息驱动:
即进程受到某个消息后,通过对消息的内容的分析然后做相应的动作。如果你把你的分布式系统设置成信号驱动的,这就表示你收到一个信号就要做一个动作而一个信号的本质其实就是一个数字而已。这样系统稍微大一点的话,系统将变得异常难以维护;甚至在很多时候,信号驱动是无法满足我们的需求的。
因此现在我们一般也不用信号了。
因此,请记住:
除非你有非常有说服力的理由,否则请用socket。
顺便给你推荐个基于socket的轻量级的消息库:ZeroMQ。
专业数据统计,95%的用户会因为[不安全]提示而放弃访问,从而给网站造成用户流失。问题就出在不安全的HTTP 明文传输协议上。2018年2月初,谷歌旗下Chrome浏览器宣布“封杀”HTTP协议的网站,并将这些网站标示为“Not Secure”(不安全)。
2023-03-03 21:141、do-while语句是一种后测试循环语句,即循环体中的代码执行后才会对退出条件进行求值。2、循环体内的代码至少执行一次。do-while的语法如下:do{ statement }while(expression)下面是一个例子:letxhs=0 do{ xhs+=2 }while(xhs<10)在上面的
2023-02-26 12:191、while语句是一种先测试循环语句,即先检测退出条件,再执行循环体内的代码。2、while循环体内的代码有可能不会执行。下面是 while 循环的语法:while(expression){ statement }实例leti=0 while(i<10){ i+=2 }在这个例子中,变量 xhs 从 0 开
2023-02-26 12:181、for语句也是先测试语句,只不过增加了进入循环之前的初始化代码.以及循环执行后要执行的表达式(loop-expression),语法如下:for(initialization;expression;loop-expression){ statement }下面是一个用例:letxhsLength=10 for(letxhs=0;xh
2023-02-26 12:17说明1、for-of语句是一种严格的迭代语句,用于遍历可迭代对象的元素。2、for-of循环将按照可迭代对象的next()方法产生值的顺序迭代元素。关于可迭代对象,请参考ES6系列的Iterator。如果尝试迭代的变量不支持迭代,for-of语句就会出错。语法:只
2023-02-26 12:16说明1、switch语句可用于所有的数据类型(在许多语言中,它只能用于数值),因此可以使用字符串甚至对象。2、条件值不一定是常量,或者是一个变量或者一个表达式。实例switch('helloxhsRookies'){ case'hello'+'xhsRookies&#
2023-02-26 12:15发布日期:2022-10-29人气:641
发布日期:2022-10-10人气:555
发布日期:2022-09-29人气:335
发布日期:2022-09-04人气:311
发布日期:2023-01-16人气:226
发布日期:2022-10-02人气:149
发布日期:2022-11-07人气:145