线程基础
1.CPU
个人pc机一般只有一个cpu,服务器通常有多个cpu。
查看window,设备管理器,几核:
查看cpu数,命令行写:systeminfo,下图是一个处理器
在cmd命令中输入“wmic”,然后在出现的新窗口中输入“cpu get *”。
NumberOfCores:表示CPU核心数
NumberOfLogicalProcessors:表示CPU线程数:
这机子六核、六线程,一比一关系,不是超线程技术。
查看linuxcpu 信息:cat /proc/cpuinfo |grep name |cut -f2 -d: | uniq -c
查看物理cpu个数: grep 'physical id' /proc/cpuinfo | sort -u
查看核心数量:grep 'core id' /proc/cpuinfo | sort -u | wc -l
查看线程数: grep 'processor' /proc/cpuinfo | sort -u | wc -l
图片里是1个cpu,1核,两个线程,所以能并行两个线程。
2.核心数、线程数
cpu可以有双核、四核、六核。
增加核数是为了增加线程数,因为操作系统通过线程去执行任务,一班核心数:线程数是1:1,但Intel引入超线程技术后,核心数:线程数可以是1:2.
假设一个cpu双核四线程,我们可以认为能够同时执行四个任务,并行四个任务。
3.进程和线程
进程是分配资源的最小单位,资源包括cpu、内存、磁盘IO等,同一条进程的多条线程共享该进程的全部资源,进程互相之间独立。
线程是cpu执行任务的最小调度单位。
4.并行和并发
并行:
程序中运行的线程数<=cpu数*cpu核数(核心数:线程数=1:1);
程序中运行的线程数<=CPU数*cpu线程数量(核心数:线程数=1:2,此线程是一个cpu最多同时能运行的数目=核*核内线程数)
如果是以上两种情况,则是并行。
并发:
程序中运行的线程数>cpu数*cpu核数(核心数:线程数=1:1);
程序中运行的线程数>CPU数*cpu线程数量
5.Runtime.getRuntime().availableProcessors()
java方法得到是线程数,但有时得到的是核数,java是去询问操作系统,由操作系统给的值,所以不能依赖它。
6.线程池
IO密集型的线程池应该和程序密集的线程池分开,不应该公用一个。
IO密集根据业务可以多设置一些线程,比如2*Cpu数*cpu线程数。
程序密集型不应该超过Cpu数*cpu线程数,还要考虑到其他程序运行。
7.锁的使用场景
锁应该用在多个线程对同一变量时进行修改时,有线程安全问题时使用。
或者对同一资源的争夺,防止资源变化超出限制,比如秒杀。
第一个场景例如websoket,每个长链接会产生一个实例,在demo版本中,会将实例放在set集合中,多个线程同时建立长链接就会有线程安全问题,例如元素错乱、运行时异常,所以将这个集合用了CopyOnWriteArraySet,这是个线程安全的set集合,但思路和锁一样防止线程安全问题。
第二个场景例如秒杀,防止超卖,多个线程同时对一个资源进行修改,防止这个资源超出业务限制。