话题一:缓存思想

wKioL1YjWRyjO5c7AACPMiizIag230.jpg


我们经常说,要想让程序快,就得多利用缓存,有一句话说的好,缓存为王!


从计算机硬件上看,我们知道有内存,CPU里面有寄存器/一级/二级/三级缓存,那么CPU里面为什么要这些东西呢?


程序是运行在内存之上的,CPU是负责计算处理数据的,想一想:

方案一:每一次CPU计算数据都是从内存里面取,计算完毕后,在写入内存

方案二:将CPU需要计算处理的数据从内存先加载进一级、二级、三级缓存,那么意味着以后CPU进行计算将从自己的缓存中拿去,而不用每次从内存中取,这样会节省很多时间!


那么什么是缓存思想呢,胖哥说的好,其实就是“就近原则”,只要我们需要处理的数据离的近,那么就计算的快!



话题二:处理指令的方法

我们在移动鼠标,敲打键盘的时候,都会发出指令,那么计算机是如何处理这么密集的指令的呢?


方法一:计算机可以每隔一段时间去扫描各个部件,看看有没有指令需要处理。

这种方法的弊端是,当扫描到的时候,可能指令早就发出了,也就是“晚了”。


方法二:如下图所示

wKiom1YjYDDQiuGQAAB9Yq03rfo707.jpg

首先来说,我们不知道设备什么时候发出指令,也不知道发出指令的频繁度,而CPU又是一个高速处理指令的部件,那么怎么办呢?


让发出的指令,进入一个指令缓冲区内,CPU从指令缓冲区内拿指令进行执行,这样起到了一个平衡的作用,而且发挥CPU的高效性!【其实这就是所谓的“中断”模型】


可见,不仅仅缓存可以提高程序的运行速度,利用缓冲区的思想对于一些系统也是一个不错的IDEA!


想一想,我们经常在JAVA IO的过程中使用BUFFER,和上面的思想不是类似的吗?



话题三:多个CPU


计算机从原先的一个CPU,弄到现在有很多个CPU,这是为什么呢?


有一堆货物,如果多个人一起来搬,会比一个人搬,要快的多!可是,人多了,是会有矛盾的,是需要复杂的算法进行管理的;而一个人,随便怎么弄!


设想一下,如果来了一个指令,多个CPU一起来争夺这个指令,都想去执行这个指令,怎么办?


既然有多个CPU,那么为什么不指定一个“老大”,出现矛盾时,就听“老大”的,这是一种实现调度的方式。



话题四:如何CACHE?

有一个CACHE LINE的概念,说的就是将一段连续的内存空间CACHE住!

比如,我们有一个一维数组,那么显然,如果一次性将数组元素CACHE到缓存中,会有利于程序的高效性,反之,如果每一次访问数组元素都是从内存中加载的话,必然效率不高。



话题五:多核CPU与多线程


我们知道在JAVA代码中,可以使用synchronized来进行锁的控制,实际上是指定了一块临界区,在这块临界区内,不管有多少个CPU,只要有一个线程进入了,那么其他线程都必须等待,实际上是将其他线程放入到了一个阻塞队列中,一旦临界区内的线程离开了,那么阻塞队列中的线程被激活。


在我们的系统中,是不是线程越多越好呢?

我们希望CPU是真正的在干活,而不是在多个线程上进行“上下文切换”。

如果我们的系统是CPU密集型,也即是大多都是计算任务,应该配置和CPU个数相关的线程数量;如果是IO密集型,其实并不占用太多CPU(阻塞IO的话),因此可以通过提供数目较多的线程来达到提高CPU的使用率。



话题六:随机读写和顺序读写

在计算机领域,经常听到上面的概念,那么到底什么是“随机”/“顺序”读写呢?


我们的数据是存储在硬盘上的,而机械式的硬盘,是需要寻道寻址的,也就是必须先转动磁头到相应位置后,在进行读写。如果,我们的IO次数较多,而且都还是些小IO的话,势必造成磁头一会儿在A处读写,一会又到B处读写,这就是所谓的“随机”的概念。


可以看得出,随机读写,会有大量的时间花费在寻道寻址上,那么什么是顺序读写呢?

如果有10条数据需要写入,那么不要先写第一条,写完了,在写第二条,而是一次性批量的写入!将多次小IO合并成大的IO,批量的,一次性写入,这就是“顺序”的概念。


感悟:我们在JAVA IO操作时,总是说数据先写入BUFFER,等缓冲区满后,在FLUSH,其实就是将随机读写变成顺序读写,从而节省IO时间!



话题七:网络IO中的一些思考


字节流 VS 字符流

在网络IO中,传输的是字节流,也就是计算机所能识别的01数字,而对于我们而言,字符是可视化的,友好的,因此会在字节流的基础上进行包装!


接收方如何知道编码?接收方如何知道结束?

如果A给B发送一串信息S,在网络中会将S弄成字节流D,B拿到后如何知道是什么呢?B又如何知道什么时候发送结束了呢?


首先来讲,S到D的过程,会利用到字符集,其实就是一个映射表,它告诉了多少个字节的数据会转化成可视化的字符数据;B拿到字节数据后,同理,利用映射表将其转化成字符数据。


可见,如果编码的过程和解码的过程采用同一的字符集的话,就不会出现“乱码”问题了。

那么,B如何知道A的编码是什么呢?


可以A,B在写代码前,商量好字符集,或者采用一种更加“智能”的方式:

想一想,浏览器和服务器在利用HTTP协议进行通信时,是不是有很多paramName=Value的数据,如果A在发送数据的时候,同时给数据打一个“标签”,明确的告诉B编码是什么,B收到数据后,先看“标签”,明确了字符集,在进行操作,这样一来,B就可以自动识别A发送数据的字符集了。


A在给B发送数据,那么B又如何知道什么时候数据结束了呢?

如果A write了一行数据,并且以\n结束,如果B收到了一行数据,还读到了\n,那么就意味着本次数据读完了。也就是writeLine()/readLine()是需要结束标记的!

那么除了结束标记外,还可以怎样呢?

如果A在发送数据前,先告诉B,我要发送N大小的数据,那么B自然接收到N大小的数据后就知道该结束了!