进程内高并发(二)

01 线程基础知识

02_从一则招聘谈起

在这里插入图片描述
线程的发展历史、编程结构的发展历史就是对CPU性能不断压榨的历史。

注意学习方法,时间多就好好理解,真正理解透彻,做到见名知意

时间不多,直接背,而且老马也建议直接背,知道吗? 但是据我的面试经验,年限少的可行,年限多的不可行,直接问深入或者实操心得,一问就懵逼,还记得腾讯互金的二面吗? 问哨兵的使用细节,一问就露馅儿。
还有分布式锁的使用场景,redis的使用场景,这些东西八股文只能应对中小厂,大厂就不行了。

03_线程的历史-CPU性能压榨的血泪史

开局一张图,放这里
在这里插入图片描述

1、单进程人工切换

纸带机 : 大量时间等着人把纸带放到CPU里。

2、多进程批处理

多个任务批量执行

3、多进程并行处理

把程序写在不同的内存位置上 来回切换: 现代操作系统压榨CPU的常用思路。

4、多线程

一个程序内不同任务的来回切换、QQ里,有的线程在等待网络IO,有的在刷新UI,有的在执行数据持久化。

selector epoll、

线程也会和网络编程模型,或者IO结合在一起。 IO的知识是面试加分项,,可以去看周老师的课。

5、Java叫纤程、go叫协程

他们是绿色线程,是用户管理的(而不是OS管理的)线程。

04_进程线程纤程区别

05_底层理解进程

在这里插入图片描述
记住上图,很经典。

比如QQ.exe文件是Windows下可运行的程序,它是磁盘里的静态文件,双击它就开始运行,操作系统找到这个可执行文件 把相关的信息load到内存,再双击一下QQ,内存里又load一份,内存里每一份QQ都称之为是一个进程。
一个程序可以运行多个,每一个都是一个进程。单例除外(比如任务管理器),操作系统 会为每个进程分配相关的资源,最重要的就是内存,还有什么文件描述符,IO端口号等都是资源。
什么时候需要执行了就把它从内存放到CPU里去执行(简单的说)。 程序load到内存里变成进程之后,就可以给它分配运行时需要的资源了,所以进程又是OS进行资源分配的基本单位(比较专业的说法)。

06_通俗理解线程

线程:一个程序里不同的执行路径。 main方法所开启的线程是主线程
多线程就是一个程序运行的时候会产生一个分支,不同的分支同时在运行,一个分支在等待程序输入,一个分支在存数据,一个分支在等待着网络的输入。 几个分支是同时运行的。

07_从底层角度理解线程

还是看上图,双击QQ.exe的时候,会load到内存变成一个进程,那程序是怎么开始执行这个进程的呢??

以下重要:
真正开始执行的时候,程序是以线程为单位来执行的,os会找到主线程(main方法),让它给到CPU去执行。
如果主线程中开启里其他线程,那线程之间就会来回的切换。 A线程交给CPU执行一会儿,B线程又交给CPU执行一会儿,这就是线程切换。

那么概念就出来了,一个进程包含多个线程。但是从概念上来说,进程是资源分配的基本单位(静态的概念),而线程是在进程的内部,是调度执行的基本单位(动态的概念),多个线程共享同一个进程里的资源。 就是共享了资源所以产生一堆麻烦事。

08_底层分析什么是线程的切换

在这里插入图片描述
线程切换也叫线程上下文切换

看这个图
作为一个程序来说,它有指令有数据,作为CPU来说它有几个重要的组成单元(计算单元 ARU、寄存器组 registers用来存储数据 的,PC也是一种寄存器 programme counter 用来存储我到底执行到哪条指令了。)
当我们执行到一个线程里,上图中所示,数据放在寄存器组里,指令放在PC。

所以 一个线程T1 执行的话,把T1的指令和数据放进CPU,然后CPU的计算单元对它进行计算,计算完了该输出输出,该做什么操作就做什么操作。
那根据os的线程调度算法,T1到时间了,它该走了,CPU不能继续服务T1了。(想要了解os的调度算法是什么样的,去看老马操作系统的课。。 )
那现在要换另外的线程T2了,要服务T2了,会发生什么呢? 把 T1线程的数据和指令地址存到缓存里去(看上图的cache),这个缓存后面会讲,把它理解成内存也可以。 总而言之就是放到旁边一个地方。再把T2的数据和指令放到CPU里,让CPU继续做计算。 所以CPU就是只管算就行,根据一个指令来算数据,其他它什么都不管。至于这个数据和指令是属于哪个线程的,CPU根本不管,这事归老大OS来管。

现在T2的时间到了,我想要T1回来继续计算,怎么办呢?
很简单撒,把T2相关是数据放进缓存,把原来T1相关的数据再放回CPU撒 (脑子始终有图)
这个过程需要os的调度,调度也是要消耗系统资源的,所以这就是线程切换的过程,专业名词叫 content switch(线程上下文切换)

09_单核CPU设定多线程是否有意义

单核CPU在一个时间点上只能跑一个线程,那设定多线程有意义吗?
当然有意义。

我们知道,线程就是一段程序做的一些操作撒,这些操作并不是全部都消耗CPU的,比如等待网络的输入就不需要(我在等待网络上传来数据呢,肯定不用消耗CPU)或者sleep的时候,也不需要,那这时候肯定要把时间让给别的线程去运行。

线程的分类:
有的叫 CPU密集型,啥意思?就是这个线程大量的时间都在做计算(如循环加减乘除),对CPU的利用率比较高。
还有的叫IO密集型,意思就是用大量的时间来等待输入输出,等待来数据之后很可能就做一个简单的拷贝。
这是两种不同的线程,不过大部分的线程即有IO 又有计算。
不同的线程要设置不同的数量,后面会讲。

10_线程数是不是越大越好_1

当然不是。线程切换是要消耗资源的。

11_线程数是不是越大越好_2

典型的多线程案例:一亿个数求和。
很简单,最起码我可以分成两份,一个线程算五千万个数,2个线程一起算不是更快么。
那问题又来了,线程数是不是设置的越多越好呢?

public class T01_MultiVSSingle_ContextSwitch {
   


    private static double[] nums = new double[1_0000_0000];
    private static Random r = new Random();
    private static DecimalFormat df = new DecimalFormat("0.00");
    static {
   
        //给nums赋值
        for (int i = 0; i < nums.length; i++) {
   
            nums[i] = r.nextDouble();;
        }
    }

    public static void m1(){
   
        long start = System.currentTimeMillis();
        double result = 0.0;
        for (int i = 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值