石杉笔记(5) 进程间通信方式、线程间切换、BIO/NIO/AIO 、线上cpu 100%、32位java虚拟机中的long和double变量写操作为何不是原子的

1、进程间的通信

通信方式:管道(pipe)、命名管道(fifo)、消息队列、共享内存(System V)

线程之间如何切换:

      一个进程的多个线程间切换的时候涉及上下文切换,就是有一个时间片算法,cpu给每个线程一个时间片来执行,时间片结束之后,就保存这个线程的状态,然后切换到下一个线程去执行,这就是所谓多线程并发执行的原理,就是多个线程来回切换,每个线程就一个时间片执行

2、BIO、NIO、AIO

BIO: 阻塞通信

 每次通信就新建一个客户端,然后新建一个对应的线程与之通信,直到通信完成,如果同时通信的线程比较多,就会导致系统宕机

 NIO: 同步非阻塞

selector多路复用器,selector会不断轮询注册的channel,如果某个channel上发生了读写事件,selector就会将这些channel获取出来,我们通过selectionKey获取有读写事件的channel,就可以进行IO操作。一个selector就通过一个线程,就可以轮询成千上万的channel,这就意味着你的服务端 可以接入成千上万的客户端

相当于一个线程处理大量的客户端的请求,通过一个线程轮询大量的channel,每次就获取一批有事件的channel,然后对每个请求启动一个线程处理即可。

这里的核心就是非阻塞,就那个 selector 一个线程就可以不停轮询 channel,所有客户端请求都不会阻塞,直接就会进来,大不了就等待一下排队而已

NIO的优化思想:一个请求一个线程,只有某个客户端发送了一个请求的时候,才会启动一个线程来处理

非阻塞: 无论多少客户端接入,客户端接入并不会耗费一个线程,只会创建一个连接,然后注册到selector上,一个 selector 线程不断的轮询所有的 socket 连接,发现有事件就通知,然后就启动一个线程处理一个请求即可,但是这个处理的过程,还是要读数,处理,再返回,这个是同步过程


同步阻塞、同步非阻塞、异步非阻塞

BIO : 同步阻塞,针对文件IO操作来说,因为用BIO的流读写文件,是说你发起IO请求直接hang死,必须等着这次IO操作才能返回;不是完全针对的网络通信模型去说的,针对的是磁盘文件的IO读写,FileInputStream,BIO卡在那儿,直到你读写完成了才可以

NIO:同步非阻塞,通过NIO的FileChannel发起个文件IO操作,其实发起之后就返回了,这就是非阻塞,但是接下来还要不断去轮询操作系统,看IO是否操作完成; 

AIO: 异步非阻塞,发起IO操作后,立马返回,操作系统干完后,会返回ok

同步就是主动去轮询操作系统,异步就是操作系统反过来通知你

 

3、线上cpu 100%

(1)定位耗费 cpu 的进程

top -c 显示进程列表,然后输入P,按照cpu使用率排序,查询那个进程,cpu负载最高,还有启动这个进程的命令

(2)定位耗费cpu的线程

top -Hp 43987 输入进程id就好了,然后输入P,按照cpu使用率排序

(3)定位那段代码导致的cpu 过载

printf "%x\n" 16872  把线程 pid转为 16进制,比如41e8

jstack 43987 | grep '41e8' -C5 --color 用jstack 打印进程的堆栈信息,而且通过grep 那个线程16进制的pid,找到那个线程相关的东西,这个时候就可以在打印出的代码里,看到是哪个类的哪个方法导致的这个cpu 100%的问题

 

4、32位java虚拟机中的long和double变量写操作为何不是原子的