通信方式:管道(pipe)、命名管道(fifo)、消息队列、共享内存(System V)
线程之间如何切换:
一个进程的多个线程间切换的时候涉及上下文切换,就是有一个时间片算法,cpu给每个线程一个时间片来执行,时间片结束之后,就保存这个线程的状态,然后切换到下一个线程去执行,这就是所谓多线程并发执行的原理,就是多个线程来回切换,每个线程就一个时间片执行
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
同步就是主动去轮询操作系统,异步就是操作系统反过来通知你
(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%的问题