为什么要用多线程
任何一项技术的出现都是为了解决现有问题。
之前的互联网大多是单机服务,体量小;而现在的更多是集群服务,同一时刻有多个用户同时访问服务器,那么会有很多线程并发访问。
比如在电商系统里,同一时刻比如整点抢购时,大量用户同时访问服务器,所以现在公司里开发的基本都是多线程的。
使用多线程确实提高了运行的效率,但与此同时,我们也需要特别注意数据的增删改情况,这就是线程安全问题,比如之前说过的 HashMap vs HashTable
,Vector vs ArrayList
。
要保证线程安全也有很多方式,比如说加锁,但又可能会出现其他问题比如死锁,所以多线程相关问题会比较麻烦。
因此,我们需要理解多线程的原理和它可能会产生的问题以及如何解决问题,才能拿下高薪职位。
进程 vs 线程
程序 program
说到进程,就不得不先说说程序。
程序,说白了就是代码,或者说是一系列指令的集合。比如「微信.exe」这就是一个程序,这个文件最终是要拿到 CPU 里面去执行的。
进程 process
当程序运行起来,它就是一个进程。
所以程序是“死”的,进程是“活”的。
比如在任务管理器里的就是一个个进程,就是“动起来”的应用程序。
Q:这些进程是并行执行的吗?
单核 CPU 一个时间片里只能执行一个进程。但是因为它切换速度很快,所以我们感受不到,就造成了一种多进程的假象。(多核 CPU 那真的就是并行执行的了。)
Q:那如果这个进程没执行完呢?
当进程 A 执行完一个时间片,但是还没执行完时,为了方便下次接着执行,要保存刚刚执行完的这些数据信息,叫做「保存现场」。
然后等下次再抢到了资源执行的时候,先「恢复现场」,再开始继续执行。
这样循环往复。。
这样反复的保存啊、恢复啊,都是额外的开销,也会让程序执行变慢。
Q:有没有更高效的方式呢?
如果两个线程归属同一个进程,就不需要保存、恢复现场了。
这就是 NIO 模型的思路,也是 NIO 模型比 BIO 模型效率高很多的原因,我们之后再讲。
线程 thread
线程,是一个进程里的具体的执行路径,就是真正干活的。
在一个进程里,一个时间片也只能有一个线程在执行,但因为时间片的切换速度非常快,所以看起来就好像是同时进行的。
一个进程里至少有一个线程。比如主线程,就是我们平时写的 main()
函数,是用户线程;还有 gc
线程是 JVM 生产的,负责垃圾回收,是守护线程。
每个线程有自己的栈 stack
,记录该线程里面的方法相互调用的关系;
但是一个进程里的所有线程是共用堆 heap
的。
那么不同的进程之间是不可以互相访问内存的,每个进程有自己的内存空间 memeory space
,也就是虚拟内存 virtual memory
。
通过这个虚拟内存,每一个进程都感觉自己拥有了整个内存空间。
虚拟内存的机制,就是屏蔽了物理内存的限制。
Q:那如果物理内存被用完了呢?
用硬盘,比如 windows 系统的分页文件,就是把一部分虚拟内存放到了硬盘上。
相应的,此时程序运行会很慢,因为硬盘的读写速度比内存慢很多,是我们可以感受到的慢,这就是为什么开多了程序电脑就会变卡的原因。
Q:那这个虚拟内存是有多大呢?
对于 64 位操作系统来说,每个程序可以用 64 个二进制位,也就是 2^64
这么大的空间!
如果还不清楚二进制相关内容的,公众号内回复「二进制」获取相应的文章哦~
总结
总结一下,在一个时间片里,一个 CPU 只能执行一个进程。
CPU 给某个进程分配资源后,这个进程开始运行;进程里的线程去抢占资源,一个时间片就只有一个线程能执行,谁先抢到就是谁的。
多进程 vs 多线程
每个进程是独立的,进程 A 出问题不会影响到进程 B;
虽然线程也是独立运行的,但是一个进程里的线程是共用同一个堆,如果某个线程 out of memory
,那么这个进程里所有的线程都完了。
所以多进程能够提高系统的容错性 fault tolerance
,而多线程最大的好处就是线程间的通信非常方便。
进程之间的通信需要借助额外的机制,比如进程间通讯 interprocess communication
- IPC
,或者网络传递等等。
最后的内容
在开头跟大家分享的时候我就说,面试我是没有做好准备的,全靠平时的积累,确实有点临时抱佛脚了,以至于我自己还是挺懊恼的。(准备好了或许可以拿个40k,没做准备只有30k+,你们懂那种感觉吗)
如何准备面试?
1、前期铺垫(技术沉积)
程序员面试其实是对于技术的一次摸底考试,你的技术牛逼,那你就是大爷。大厂对于技术的要求主要体现在:基础,原理,深入研究源码,广度,实战五个方面,也只有将原理理论结合实战才能把技术点吃透。
下面是我会看的一些资料笔记,希望能帮助大家由浅入深,由点到面的学习Java,应对大厂面试官的灵魂追问,有需要的话就戳这里:蓝色传送门打包带走吧。
这部分内容过多,小编只贴出部分内容展示给大家了,见谅见谅!
- Java程序员必看《Java开发核心笔记(华山版)》
- Redis学习笔记
- Java并发编程学习笔记
四部分,详细拆分并发编程——并发编程+模式篇+应用篇+原理篇
- Java程序员必看书籍《深入理解 ava虚拟机第3版》(pdf版)
- 大厂面试必问——数据结构与算法汇集笔记
其他像Spring,SpringBoot,SpringCloud,SpringCloudAlibaba,Dubbo,Zookeeper,Kafka,RocketMQ,RabbitMQ,Netty,MySQL,Docker,K8s等等我都整理好,这里就不一一展示了。
2、狂刷面试题
技术主要是体现在平时的积累实用,面试前准备两个月的时间再好好复习一遍,紧接着就可以刷面试题了,下面这些面试题都是小编精心整理的,贴给大家看看。
①大厂高频45道笔试题(智商题)
②BAT大厂面试总结(部分内容截图)
③面试总结
3、结合实际,修改简历
程序员的简历一定要多下一些功夫,尤其是对一些字眼要再三斟酌,如“精通、熟悉、了解”这三者的区别一定要区分清楚,否则就是在给自己挖坑了。当然不会包装,我可以将我的简历给你参考参考,如果还不够,那下面这些简历模板任你挑选:
以上分享,希望大家可以在金三银四跳槽季找到一份好工作,但千万也记住,技术一定是平时工作种累计或者自学(或报班跟着老师学)通过实战累计的,千万不要临时抱佛脚。
另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。
望大家可以在金三银四跳槽季找到一份好工作,但千万也记住,技术一定是平时工作种累计或者自学(或报班跟着老师学)通过实战累计的,千万不要临时抱佛脚。
另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。
以上文章中,提及到的所有的笔记内容、面试题等资料,均可以免费分享给大家学习,有需要的话就戳这里打包带走吧。