1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-25 02:27:10 +08:00

Update 美团面试常见问题总结.md

This commit is contained in:
Snailclimb 2019-11-27 08:49:57 +08:00
parent d6ad33c38e
commit 6e286c6897

View File

@ -1,28 +1,28 @@
<!-- MarkdownTOC --> <!-- TOC -->
- [一 基础篇](#一-基础篇) - [一 基础篇](#一-基础篇)
- [1. `System.out.println(3|9)`输出什么?](#1-systemoutprintln39输出什么) - [1. `System.out.println(3|9)`输出什么?](#1-systemoutprintln39输出什么)
- [2. 说一下转发\(Forward\)和重定向\(Redirect\)的区别](#2-说一下转发forward和重定向redirect的区别) - [2. 说一下转发(Forward)和重定向(Redirect)的区别](#2-说一下转发forward和重定向redirect的区别)
- [3. 在浏览器中输入url地址到显示主页的过程,整个过程会使用哪些协议](#3-在浏览器中输入url地址到显示主页的过程整个过程会使用哪些协议) - [3. 在浏览器中输入 url 地址到显示主页的过程,整个过程会使用哪些协议](#3-在浏览器中输入-url-地址到显示主页的过程整个过程会使用哪些协议)
- [4. TCP 三次握手和四次挥手](#4-tcp-三次握手和四次挥手) - [4. TCP 三次握手和四次挥手](#4-tcp-三次握手和四次挥手)
- [为什么要三次握手](#为什么要三次握手) - [为什么要三次握手](#为什么要三次握手)
- [为什么要传回 SYN](#为什么要传回-syn) - [为什么要传回 SYN](#为什么要传回-syn)
- [传了 SYN,为啥还要传 ACK](#传了-syn为啥还要传-ack) - [传了 SYN,为啥还要传 ACK](#传了-syn为啥还要传-ack)
- [为什么要四次挥手](#为什么要四次挥手) - [为什么要四次挥手](#为什么要四次挥手)
- [5. IP地址与MAC地址的区别](#5-ip地址与mac地址的区别) - [5. IP 地址与 MAC 地址的区别](#5-ip-地址与-mac-地址的区别)
- [6. HTTP请求,响应报文格式](#6-http请求响应报文格式) - [6. HTTP 请求,响应报文格式](#6-http-请求响应报文格式)
- [7. 为什么要使用索引?索引这么多优点,为什么不对表中的每一个列创建一个索引呢?索引是如何提高查询速度的?说一下使用索引的注意事项?Mysql索引主要使用的两种数据结构?什么是覆盖索引?](#7-为什么要使用索引索引这么多优点为什么不对表中的每一个列创建一个索引呢索引是如何提高查询速度的说一下使用索引的注意事项mysql索引主要使用的两种数据结构什么是覆盖索引) - [7. 为什么要使用索引?索引这么多优点,为什么不对表中的每一个列创建一个索引呢?索引是如何提高查询速度的?说一下使用索引的注意事项?Mysql 索引主要使用的两种数据结构?什么是覆盖索引?](#7-为什么要使用索引索引这么多优点为什么不对表中的每一个列创建一个索引呢索引是如何提高查询速度的说一下使用索引的注意事项mysql-索引主要使用的两种数据结构什么是覆盖索引)
- [8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不?](#8-进程与线程的区别是什么进程间的几种通信方式说一下线程间的几种通信方式知道不) - [8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不?](#8-进程与线程的区别是什么进程间的几种通信方式说一下线程间的几种通信方式知道不)
- [9. 为什么要用单例模式?手写几种线程安全的单例模式?](#9-为什么要用单例模式手写几种线程安全的单例模式) - [9. 为什么要用单例模式?手写几种线程安全的单例模式?](#9-为什么要用单例模式手写几种线程安全的单例模式)
- [10. 简单介绍一下bean;知道Spring的bean的作用域与生命周期吗?](#10-简单介绍一下bean知道spring的bean的作用域与生命周期吗) - [10. 简单介绍一下 bean;知道 Spring bean 的作用域与生命周期吗?](#10-简单介绍一下-bean知道-spring--bean-的作用域与生命周期吗)
- [11. Spring 中的事务传播行为了解吗?TransactionDefinition 接口中哪五个表示隔离级别的常量?](#11-spring-中的事务传播行为了解吗transactiondefinition-接口中哪五个表示隔离级别的常量) - [11. Spring 中的事务传播行为了解吗?TransactionDefinition 接口中哪五个表示隔离级别的常量?](#11-spring-中的事务传播行为了解吗transactiondefinition-接口中哪五个表示隔离级别的常量)
- [事务传播行为](#事务传播行为) - [事务传播行为](#事务传播行为)
- [隔离级别](#隔离级别) - [隔离级别](#隔离级别)
- [12. SpringMVC 原理了解吗?](#12-springmvc-原理了解吗) - [12. SpringMVC 原理了解吗?](#12-springmvc-原理了解吗)
- [13. Spring AOP IOC 实现原理](#13-spring-aop-ioc-实现原理) - [13. Spring AOP IOC 实现原理](#13-spring-aop-ioc-实现原理)
- [二 进阶篇](#二-进阶篇) - [二 进阶篇](#二-进阶篇)
- [1 消息队列MQ的套路](#1-消息队列mq的套路) - [1 消息队列 MQ 的套路](#1-消息队列-mq-的套路)
- [1.1 介绍一下消息队列MQ的应用场景/使用消息队列的好处](#11-介绍一下消息队列mq的应用场景使用消息队列的好处) - [1.1 介绍一下消息队列 MQ 的应用场景/使用消息队列的好处](#11-介绍一下消息队列-mq-的应用场景使用消息队列的好处)
- [1)通过异步处理提高系统性能](#1通过异步处理提高系统性能) - [1)通过异步处理提高系统性能](#1通过异步处理提高系统性能)
- [2)降低系统耦合性](#2降低系统耦合性) - [2)降低系统耦合性](#2降低系统耦合性)
- [1.2 那么使用消息队列会带来什么问题?考虑过这些问题吗?](#12-那么使用消息队列会带来什么问题考虑过这些问题吗) - [1.2 那么使用消息队列会带来什么问题?考虑过这些问题吗?](#12-那么使用消息队列会带来什么问题考虑过这些问题吗)
@ -31,51 +31,49 @@
- [2 谈谈 InnoDB 和 MyIsam 两者的区别](#2-谈谈-innodb-和-myisam-两者的区别) - [2 谈谈 InnoDB 和 MyIsam 两者的区别](#2-谈谈-innodb-和-myisam-两者的区别)
- [2.1 两者的对比](#21-两者的对比) - [2.1 两者的对比](#21-两者的对比)
- [2.2 关于两者的总结](#22-关于两者的总结) - [2.2 关于两者的总结](#22-关于两者的总结)
- [3 聊聊 Java 中的集合吧!](#3-聊聊-java-中的集合吧) - [3 聊聊 Java 中的集合吧!](#3-聊聊-java-中的集合吧)
- [3.1 ArrayList 与 LinkedList 有什么不同?\(注意加上从数据结构分析的内容\)](#31-arraylist-与-linkedlist-有什么不同注意加上从数据结构分析的内容) - [3.1 Arraylist 与 LinkedList 有什么不同?(注意加上从数据结构分析的内容)](#31-arraylist-与-linkedlist-有什么不同注意加上从数据结构分析的内容)
- [3.2 HashMap的底层实现](#32-hashmap的底层实现) - [3.2 HashMap 的底层实现](#32-hashmap-的底层实现)
- [1)JDK1.8之前](#1jdk18之前) - [1)JDK1.8 之前](#1jdk18-之前)
- [2)JDK1.8之后](#2jdk18之后) - [2)JDK1.8 之后](#2jdk18-之后)
- [3.3 既然谈到了红黑树,你给我手绘一个出来吧,然后简单讲一下自己对于红黑树的理解](#33-既然谈到了红黑树你给我手绘一个出来吧然后简单讲一下自己对于红黑树的理解) - [3.3 既然谈到了红黑树,你给我手绘一个出来吧,然后简单讲一下自己对于红黑树的理解](#33-既然谈到了红黑树你给我手绘一个出来吧然后简单讲一下自己对于红黑树的理解)
- [3.4 红黑树这么优秀,为何不直接使用红黑树得了?](#34-红黑树这么优秀为何不直接使用红黑树得了) - [3.4 红黑树这么优秀,为何不直接使用红黑树得了?](#34-红黑树这么优秀为何不直接使用红黑树得了)
- [3.5 HashMap 和 Hashtable 的区别/HashSet 和 HashMap 区别](#35-hashmap-和-hashtable-的区别hashset-和-hashmap-区别) - [3.5 HashMap 和 Hashtable 的区别/HashSet 和 HashMap 区别](#35-hashmap-和-hashtable-的区别hashset-和-hashmap-区别)
- [三 终结篇](#三-终结篇) - [三 终结篇](#三-终结篇)
- [1. Object类有哪些方法?](#1-object类有哪些方法) - [1. Object 类有哪些方法?](#1-object-类有哪些方法)
- [1.1 Object类的常见方法总结](#11-object类的常见方法总结) - [1.1 Object 类的常见方法总结](#11-object-类的常见方法总结)
- [1.2 hashCode与equals](#12-hashcode与equals) - [1.2 hashCode equals](#12-hashcode--equals)
- [1.2.1 hashCode\(\)介绍](#121-hashcode介绍) - [1.2.1 hashCode()介绍](#121-hashcode介绍)
- [1.2.2 为什么要有hashCode](#122-为什么要有hashcode) - [1.2.2 为什么要有 hashCode](#122-为什么要有-hashcode)
- [1.2.3 hashCode\(\)与equals\(\)的相关规定](#123-hashcode与equals的相关规定) - [1.2.3 hashCode()与 equals()的相关规定](#123-hashcode与-equals的相关规定)
- [1.2.4 为什么两个对象有相同的hashcode值,它们也不一定是相等的?](#124-为什么两个对象有相同的hashcode值它们也不一定是相等的) - [1.2.4 为什么两个对象有相同的 hashcode 值,它们也不一定是相等的?](#124-为什么两个对象有相同的-hashcode-值它们也不一定是相等的)
- [1.3 ==与equals](#13-与equals) - [1.3 ==与 equals](#13-与-equals)
- [2 ConcurrentHashMap 相关问题](#2-concurrenthashmap-相关问题) - [2 ConcurrentHashMap 相关问题](#2-concurrenthashmap-相关问题)
- [2.1 ConcurrentHashMap 和 Hashtable 的区别](#21-concurrenthashmap-和-hashtable-的区别) - [2.1 ConcurrentHashMap 和 Hashtable 的区别](#21-concurrenthashmap-和-hashtable-的区别)
- [2.2 ConcurrentHashMap线程安全的具体实现方式/底层具体实现](#22-concurrenthashmap线程安全的具体实现方式底层具体实现) - [2.2 ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](#22-concurrenthashmap-线程安全的具体实现方式底层具体实现)
- [JDK1.7\(上面有示意图\)](#jdk17上面有示意图) - [JDK1.7(上面有示意图)](#jdk17上面有示意图)
- [JDK1.8\(上面有示意图\)](#jdk18上面有示意图) - [JDK1.8(上面有示意图)](#jdk18上面有示意图)
- [3 谈谈 synchronized 和 ReenTrantLock 的区别](#3-谈谈-synchronized-和-reentrantlock-的区别) - [3 谈谈 synchronized 和 ReentrantLock 的区别](#3-谈谈-synchronized-和-reentrantlock-的区别)
- [4 线程池了解吗?](#4-线程池了解吗) - [4 线程池了解吗?](#4-线程池了解吗)
- [4.1 为什么要用线程池?](#41-为什么要用线程池) - [4.1 为什么要用线程池?](#41-为什么要用线程池)
- [4.2 Java 提供了哪几种线程池?他们各自的使用场景是什么?](#42-java-提供了哪几种线程池他们各自的使用场景是什么) - [4.2 Java 提供了哪几种线程池?他们各自的使用场景是什么?](#42-java-提供了哪几种线程池他们各自的使用场景是什么)
- [Java 主要提供了下面4种线程池](#java-主要提供了下面4种线程池) - [Java 主要提供了下面 4 种线程池](#java-主要提供了下面-4-种线程池)
- [各种线程池的适用场景介绍](#各种线程池的适用场景介绍) - [各种线程池的适用场景介绍](#各种线程池的适用场景介绍)
- [4.3 创建的线程池的方式](#43-创建的线程池的方式) - [4.3 创建的线程池的方式](#43-创建的线程池的方式)
- [5 Nginx](#5-nginx) - [5 Nginx](#5-nginx)
- [5.1 简单介绍一下Nginx](#51-简单介绍一下nginx) - [5.1 简单介绍一下 Nginx](#51-简单介绍一下-nginx)
- [反向代理](#反向代理) - [反向代理](#反向代理)
- [负载均衡](#负载均衡) - [负载均衡](#负载均衡)
- [动静分离](#动静分离) - [动静分离](#动静分离)
- [5.2 为什么要用 Nginx?](#52-为什么要用-nginx) - [5.2 为什么要用 Nginx?](#52-为什么要用-nginx)
- [5.3 Nginx 的四个主要组成部分了解吗?](#53-nginx-的四个主要组成部分了解吗) - [5.3 Nginx 的四个主要组成部分了解吗?](#53-nginx-的四个主要组成部分了解吗)
<!-- /MarkdownTOC --> <!-- /TOC -->
这些问题是 2018 年去美团面试的同学被问到的一些常见的问题,希望对你有帮助! 这些问题是 2018 年去美团面试的同学被问到的一些常见的问题,希望对你有帮助!
# 一 基础篇 # 一 基础篇
## 1. `System.out.println(3|9)`输出什么? ## 1. `System.out.println(3|9)`输出什么?
正确答案11。 正确答案11。
@ -115,7 +113,6 @@ request.getRequestDispatcher("login_success.jsp").forward(request, response);
3. **从运用地方来说**forward一般用于用户登陆的时候根据角色转发到相应的模块。redirect一般用于用户注销登陆时返回主页面和跳转到其它的网站等。 3. **从运用地方来说**forward一般用于用户登陆的时候根据角色转发到相应的模块。redirect一般用于用户注销登陆时返回主页面和跳转到其它的网站等。
4. **从效率来说**forward高。redirect低。 4. **从效率来说**forward高。redirect低。
## 3. 在浏览器中输入 url 地址到显示主页的过程,整个过程会使用哪些协议 ## 3. 在浏览器中输入 url 地址到显示主页的过程,整个过程会使用哪些协议
图片来源:《图解 HTTP》 图片来源:《图解 HTTP》
@ -133,7 +130,11 @@ request.getRequestDispatcher("login_success.jsp").forward(request, response);
具体可以参考下面这篇文章: 具体可以参考下面这篇文章:
- [https://segmentfault.com/a/1190000006879700](https://segmentfault.com/a/1190000006879700) - [https://segmentfault.com/a/1190000006879700](https://segmentfault.com/a/1190000006879700 "https://segmentfault.com/a/1190000006879700")
> 修正 [issue-568](https://github.com/Snailclimb/JavaGuide/issues/568 "issue-568"):上图中 IP 数据包在路由器之间使用的协议为 OPSF 协议错误,应该为 OSPF 协议 。
>
> IP 数据包在路由器之间传播大致分为 IGP 和 BGP 协议,而 IGP 目前主流为 OSPF 协议,思科,华为和 H3C 等主流厂商都有各自实现并使用BGP 协议为不同 AS自治系统号间路由传输也分为 I-BGP 和 E-BGP详细资料请查看《TCP/IP 卷一》
## 4. TCP 三次握手和四次挥手 ## 4. TCP 三次握手和四次挥手
@ -164,17 +165,15 @@ request.getRequestDispatcher("login_success.jsp").forward(request, response);
所以三次握手就能确认双发收发功能都正常,缺一不可。 所以三次握手就能确认双发收发功能都正常,缺一不可。
#### 为什么要传回 SYN #### 为什么要传回 SYN
接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。 接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。
> SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符 ,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。 ])消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。 > SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符 ,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。 ])消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
#### 传了 SYN,为啥还要传 ACK #### 传了 SYN,为啥还要传 ACK
双方通信无误必须是两者互相发送信息都无误。传了 SYN证明发送方主动关闭方到接收方被动关闭方的通道没有问题但是接收方到发送方的通道还需要 ACK 信号来进行验证。 双方通信无误必须是两者互相发送信息都无误。传了 SYN证明发送方主动关闭方到接收方被动关闭方的通道没有问题但是接收方到发送方的通道还需要 ACK 信号来进行验证。
断开一个 TCP 连接则需要“四次挥手”: 断开一个 TCP 连接则需要“四次挥手”:
- 客户端-发送一个 FIN用来关闭客户端到服务器的数据传送 - 客户端-发送一个 FIN用来关闭客户端到服务器的数据传送
@ -182,36 +181,29 @@ request.getRequestDispatcher("login_success.jsp").forward(request, response);
- 服务器-关闭与客户端的连接,发送一个 FIN 给客户端 - 服务器-关闭与客户端的连接,发送一个 FIN 给客户端
- 客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加 1 - 客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加 1
#### 为什么要四次挥手 #### 为什么要四次挥手
任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。 任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。
举个例子A 和 B 打电话通话即将结束后A 说“我没啥要说的了”B 回答“我知道了”,但是 B 可能还会有要说的话A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”A 回答“知道了”,这样通话才算结束。 举个例子A 和 B 打电话通话即将结束后A 说“我没啥要说的了”B 回答“我知道了”,但是 B 可能还会有要说的话A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”A 回答“知道了”,这样通话才算结束。
上面讲的比较概括,推荐一篇讲的比较细致的文章:[https://blog.csdn.net/qzcsu/article/details/72861891](https://blog.csdn.net/qzcsu/article/details/72861891) 上面讲的比较概括,推荐一篇讲的比较细致的文章:[https://blog.csdn.net/qzcsu/article/details/72861891](https://blog.csdn.net/qzcsu/article/details/72861891 "https://blog.csdn.net/qzcsu/article/details/72861891")
## 5. IP 地址与 MAC 地址的区别 ## 5. IP 地址与 MAC 地址的区别
参考:[https://blog.csdn.net/guoweimelon/article/details/50858597](https://blog.csdn.net/guoweimelon/article/details/50858597) 参考:[https://blog.csdn.net/guoweimelon/article/details/50858597](https://blog.csdn.net/guoweimelon/article/details/50858597 "https://blog.csdn.net/guoweimelon/article/details/50858597")
IP 地址是指互联网协议地址Internet Protocol AddressIP Address 的缩写。IP 地址是 IP 协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。 IP 地址是指互联网协议地址Internet Protocol AddressIP Address 的缩写。IP 地址是 IP 协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。
MAC 地址又称为物理地址、硬件地址用来定义网络设备的位置。网卡的物理地址通常是由网卡生产厂家写入网卡的具有全球唯一性。MAC 地址用于在网络中唯一标示一个网卡,一台电脑会有一或多个网卡,每个网卡都需要有一个唯一的 MAC 地址。 MAC 地址又称为物理地址、硬件地址用来定义网络设备的位置。网卡的物理地址通常是由网卡生产厂家写入网卡的具有全球唯一性。MAC 地址用于在网络中唯一标示一个网卡,一台电脑会有一或多个网卡,每个网卡都需要有一个唯一的 MAC 地址。
## 6. HTTP 请求,响应报文格式 ## 6. HTTP 请求,响应报文格式
HTTP 请求报文主要由请求行、请求头部、请求正文 3 部分组成 HTTP 请求报文主要由请求行、请求头部、请求正文 3 部分组成
HTTP 响应报文主要由状态行、响应头部、响应正文 3 部分组成 HTTP 响应报文主要由状态行、响应头部、响应正文 3 部分组成
详细内容可以参考:[https://blog.csdn.net/a19881029/article/details/14002273](https://blog.csdn.net/a19881029/article/details/14002273) 详细内容可以参考:[https://blog.csdn.net/a19881029/article/details/14002273](https://blog.csdn.net/a19881029/article/details/14002273 "https://blog.csdn.net/a19881029/article/details/14002273")
## 7. 为什么要使用索引?索引这么多优点,为什么不对表中的每一个列创建一个索引呢?索引是如何提高查询速度的?说一下使用索引的注意事项?Mysql 索引主要使用的两种数据结构?什么是覆盖索引? ## 7. 为什么要使用索引?索引这么多优点,为什么不对表中的每一个列创建一个索引呢?索引是如何提高查询速度的?说一下使用索引的注意事项?Mysql 索引主要使用的两种数据结构?什么是覆盖索引?
@ -253,15 +245,14 @@ HTTP响应报文主要由状态行、响应头部、响应正文3部分组成
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称 如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称
之为“覆盖索引”。我们知道在 InnoDB 存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次,这样就会比较慢。覆盖索引就是把要查询出的列和索引是对应的,不做回表操作! 之为“覆盖索引”。我们知道在 InnoDB 存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次,这样就会比较慢。覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!
## 8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不? ## 8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不?
**进程与线程的区别是什么?** **进程与线程的区别是什么?**
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。另外,也正是因为共享资源,所以线程中执行时一般都要进行同步和互斥。总的来说,进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。另外,也正是因为共享资源,所以线程中执行时一般都要进行同步和互斥。总的来说,进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
**进程间的几种通信方式说一下?** **进程间的几种通信方式说一下?**
1. **管道pipe**:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。管道分为 pipe无名管道和 fifo命名管道两种有名管道也是半双工的通信方式但是它允许无亲缘关系进程间通信。 1. **管道pipe**:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有血缘关系的进程间使用。进程的血缘关系通常指父子进程关系。管道分为 pipe无名管道和 fifo命名管道两种有名管道也是半双工的通信方式但是它允许无亲缘关系进程间通信。
2. **信号量semophore**:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 2. **信号量semophore**:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它通常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
3. **消息队列message queue**:消息队列是由消息组成的链表,存放在内核中 并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。消息队列与管道通信相比,其优势是对每个消息指定特定的消息类型,接收的时候不需要按照队列次序,而是可以根据自定义条件接收特定类型的消息。 3. **消息队列message queue**:消息队列是由消息组成的链表,存放在内核中 并由消息队列标识符标识。消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。消息队列与管道通信相比,其优势是对每个消息指定特定的消息类型,接收的时候不需要按照队列次序,而是可以根据自定义条件接收特定类型的消息。
@ -343,7 +334,6 @@ Spring中的bean默认都是单例的这些单例Bean在多线程程序下如
Spring 的 bean 的生命周期以及更多内容可以查看:[一文轻松搞懂 Spring 中 bean 的作用域与生命周期](https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484400&idx=2&sn=7201eb365102fce017f89cb3527fb0bc&chksm=fd985591caefdc872a2fac897288119f94c345e4e12150774f960bf5f816b79e4b9b46be3d7f&token=1990180468&lang=zh_CN#rd) Spring 的 bean 的生命周期以及更多内容可以查看:[一文轻松搞懂 Spring 中 bean 的作用域与生命周期](https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484400&idx=2&sn=7201eb365102fce017f89cb3527fb0bc&chksm=fd985591caefdc872a2fac897288119f94c345e4e12150774f960bf5f816b79e4b9b46be3d7f&token=1990180468&lang=zh_CN#rd)
## 11. Spring 中的事务传播行为了解吗?TransactionDefinition 接口中哪五个表示隔离级别的常量? ## 11. Spring 中的事务传播行为了解吗?TransactionDefinition 接口中哪五个表示隔离级别的常量?
#### 事务传播行为 #### 事务传播行为
@ -367,7 +357,6 @@ Spring的bean的生命周期以及更多内容可以查看[一文轻松搞懂
- TransactionDefinition.PROPAGATION_NESTED 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED。 - TransactionDefinition.PROPAGATION_NESTED 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED。
#### 隔离级别 #### 隔离级别
TransactionDefinition 接口中定义了五个表示隔离级别的常量: TransactionDefinition 接口中定义了五个表示隔离级别的常量:
@ -407,6 +396,7 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
**《大型网站技术架构》第四章和第七章均有提到消息队列对应用性能及扩展性的提升。** **《大型网站技术架构》第四章和第七章均有提到消息队列对应用性能及扩展性的提升。**
#### 1)通过异步处理提高系统性能 #### 1)通过异步处理提高系统性能
![通过异步处理提高系统性能](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/通过异步处理提高系统性能.jpg) ![通过异步处理提高系统性能](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/通过异步处理提高系统性能.jpg)
如上图,**在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。** 如上图,**在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。**
@ -415,11 +405,12 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
因为**用户请求数据写入消息队列之后就立即返回给用户了,但是请求数据在后续的业务校验、写数据库等操作中可能失败**。因此使用消息队列进行异步处理之后,需要**适当修改业务流程进行配合**,比如**用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功**,以免交易纠纷。这就类似我们平时手机订火车票和电影票。 因为**用户请求数据写入消息队列之后就立即返回给用户了,但是请求数据在后续的业务校验、写数据库等操作中可能失败**。因此使用消息队列进行异步处理之后,需要**适当修改业务流程进行配合**,比如**用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功**,以免交易纠纷。这就类似我们平时手机订火车票和电影票。
#### 2)降低系统耦合性 #### 2)降低系统耦合性
我们知道模块分布式部署以后聚合方式通常有两种1.**分布式消息队列**和 2.**分布式服务**。 我们知道模块分布式部署以后聚合方式通常有两种1.**分布式消息队列**和 2.**分布式服务**。
> **先来简单说一下分布式服务:** > **先来简单说一下分布式服务:**
目前使用比较多的用来构建**SOAService Oriented Architecture面向服务体系结构**的**分布式服务框架**是阿里巴巴开源的**Dubbo**。如果想深入了解Dubbo的可以看我写的关于Dubbo的这一篇文章**《高性能优秀的服务框架-dubbo介绍》**[https://juejin.im/post/5acadeb1f265da2375072f9c](https://juejin.im/post/5acadeb1f265da2375072f9c) 目前使用比较多的用来构建**SOAService Oriented Architecture 面向服务体系结构)**的**分布式服务框架**是阿里巴巴开源的**Dubbo**。如果想深入了解 Dubbo 的可以看我写的关于 Dubbo 的这一篇文章:**《高性能优秀的服务框架-dubbo 介绍》**[https://juejin.im/post/5acadeb1f265da2375072f9c](https://juejin.im/post/5acadeb1f265da2375072f9c "https://juejin.im/post/5acadeb1f265da2375072f9c")
> **再来谈我们的分布式消息队列:** > **再来谈我们的分布式消息队列:**
@ -448,9 +439,8 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
### 1.3 介绍一下你知道哪几种消息队列,该如何选择呢? ### 1.3 介绍一下你知道哪几种消息队列,该如何选择呢?
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka | | 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
| :---------------------- | -----------------------------------------------------------: | -----------------------------------------------------------: | -----------------------------------------------------------: | -----------------------------------------------------------: | | :----------------------- | -----------------------------------------------------------: | -----------------------------------------------------------: | -----------------------------------------------------------: | -----------------------------------------------------------: |
| 单机吞吐量 | 万级,吞吐量比 RocketMQ 和 Kafka 要低了一个数量级 | 万级,吞吐量比 RocketMQ 和 Kafka 要低了一个数量级 | 10 万级RocketMQ 也是可以支撑高吞吐的一种 MQ | 10 万级别,这是 kafka 最大的优点,就是吞吐量高。一般配合大数据类的系统来进行实时数据计算、日志采集等场景 | | 单机吞吐量 | 万级,吞吐量比 RocketMQ 和 Kafka 要低了一个数量级 | 万级,吞吐量比 RocketMQ 和 Kafka 要低了一个数量级 | 10 万级RocketMQ 也是可以支撑高吞吐的一种 MQ | 10 万级别,这是 kafka 最大的优点,就是吞吐量高。一般配合大数据类的系统来进行实时数据计算、日志采集等场景 |
| topic 数量对吞吐量的影响 | | | topic 可以达到几百,几千个的级别,吞吐量会有较小幅度的下降这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic | topic 从几十个到几百个的时候吞吐量会大幅度下降。所以在同等机器下kafka 尽量保证 topic 数量不要过多。如果要支撑大规模 topic需要增加更多的机器资源 | | topic 数量对吞吐量的影响 | | | topic 可以达到几百,几千个的级别,吞吐量会有较小幅度的下降这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic | topic 从几十个到几百个的时候吞吐量会大幅度下降。所以在同等机器下kafka 尽量保证 topic 数量不要过多。如果要支撑大规模 topic需要增加更多的机器资源 |
| 可用性 | 高,基于主从架构实现高可用性 | 高,基于主从架构实现高可用性 | 非常高,分布式架构 | 非常高kafka 是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 | | 可用性 | 高,基于主从架构实现高可用性 | 高,基于主从架构实现高可用性 | 非常高,分布式架构 | 非常高kafka 是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
@ -470,24 +460,20 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
5. 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决? 5. 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?
6. 如果让你来开发一个消息队列中间件,你会怎么设计架构? 6. 如果让你来开发一个消息队列中间件,你会怎么设计架构?
## 2 谈谈 InnoDB 和 MyIsam 两者的区别 ## 2 谈谈 InnoDB 和 MyIsam 两者的区别
### 2.1 两者的对比 ### 2.1 两者的对比
1. **count运算上的区别:** 因为MyISAM缓存有表meta-data行数等因此在做COUNT(*)时对于一个结构很好的查询是不需要消耗多少资源的。而对于InnoDB来说则没有这种缓存 1. **count 运算上的区别:** 因为 MyISAM 缓存有表 meta-data行数等因此在做 COUNT(\*)时对于一个结构很好的查询是不需要消耗多少资源的。而对于 InnoDB 来说,则没有这种缓存
2. **是否支持事务和崩溃后的安全恢复:** MyISAM 强调的是性能,每次查询具有原子性,其执行速度比 InnoDB 类型更快,但是不提供事务支持。但是 InnoDB 提供事务支持,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。 2. **是否支持事务和崩溃后的安全恢复:** MyISAM 强调的是性能,每次查询具有原子性,其执行速度比 InnoDB 类型更快,但是不提供事务支持。但是 InnoDB 提供事务支持,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
3. **是否支持外键:** MyISAM 不支持,而 InnoDB 支持。 3. **是否支持外键:** MyISAM 不支持,而 InnoDB 支持。
### 2.2 关于两者的总结 ### 2.2 关于两者的总结
MyISAM 更适合读密集的表,而 InnoDB 更适合写密集的表。 在数据库做主从分离的情况下,经常选择 MyISAM 作为主库的存储引擎。 MyISAM 更适合读密集的表,而 InnoDB 更适合写密集的表。 在数据库做主从分离的情况下,经常选择 MyISAM 作为主库的存储引擎。
一般来说,如果需要事务支持,并且有较高的并发读取频率(MyISAM 的表锁的粒度太大,所以当该表写并发量较高时,要等待的查询就会很多了)InnoDB 是不错的选择。如果你的数据量很大MyISAM 支持压缩特性可以减少磁盘的空间占用而且不需要支持事务时MyISAM 是最好的选择。 一般来说,如果需要事务支持,并且有较高的并发读取频率(MyISAM 的表锁的粒度太大,所以当该表写并发量较高时,要等待的查询就会很多了)InnoDB 是不错的选择。如果你的数据量很大MyISAM 支持压缩特性可以减少磁盘的空间占用而且不需要支持事务时MyISAM 是最好的选择。
## 3 聊聊 Java 中的集合吧! ## 3 聊聊 Java 中的集合吧!
### 3.1 Arraylist 与 LinkedList 有什么不同?(注意加上从数据结构分析的内容) ### 3.1 Arraylist 与 LinkedList 有什么不同?(注意加上从数据结构分析的内容)
@ -519,10 +505,9 @@ public interface RandomAccess {
} }
``` ```
ArraysList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢我觉得还是和底层数据结构有关ArraysList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1) ,所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n) 所以不支持快速随机访问。ArraysList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能。 RandomAccess 接口只是标识,并不是说 ArraysList 实现 RandomAccess 接口才具有快速随机访问功能的! ArraysList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢我觉得还是和底层数据结构有关ArraysList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1) ,所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n) 所以不支持快速随机访问。ArraysList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能。 RandomAccess 接口只是标识,并不是说 ArraysList 实现 RandomAccess 接口才具有快速随机访问功能的!
**下面再总结一下 list 的遍历方式选择:** **下面再总结一下 list 的遍历方式选择:**
- 实现了 RandomAccess 接口的 list优先选择普通 for 循环 ,其次 foreach, - 实现了 RandomAccess 接口的 list优先选择普通 for 循环 ,其次 foreach,
@ -551,6 +536,7 @@ JDK 1.8 的 hash方法 相比于 JDK 1.7 hash 方法更加简化,但是原理
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
} }
``` ```
对比一下 JDK1.7 的 HashMap 的 hash 方法源码. 对比一下 JDK1.7 的 HashMap 的 hash 方法源码.
```java ```java
@ -570,7 +556,6 @@ static int hash(int h) {
![jdk1.8之前的内部结构-HashMap](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/jdk1.8之前的内部结构-HashMap.jpg) ![jdk1.8之前的内部结构-HashMap](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/jdk1.8之前的内部结构-HashMap.jpg)
#### 2)JDK1.8 之后 #### 2)JDK1.8 之后
相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8将链表转化为红黑树以减少搜索时间。 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8将链表转化为红黑树以减少搜索时间。
@ -593,7 +578,6 @@ TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红
4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定); 4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定);
5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度) 5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)
**红黑树的应用:** **红黑树的应用:**
TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。 TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。
@ -602,7 +586,6 @@ TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。
简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。 简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
### 3.4 红黑树这么优秀,为何不直接使用红黑树得了? ### 3.4 红黑树这么优秀,为何不直接使用红黑树得了?
说一下自己对于这个问题的看法:我们知道红黑树属于(自)平衡二叉树,但是为了保持“平衡”是需要付出代价的,红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,这费事啊。你说说我们引入红黑树就是为了查找数据快,如果链表长度很短的话,根本不需要引入红黑树的,你引入之后还要付出代价维持它的平衡。但是链表过长就不一样了。至于为什么选 8 这个值呢?通过概率统计所得,这个值是综合查询成本和新增元素成本得出的最好的一个值。 说一下自己对于这个问题的看法:我们知道红黑树属于(自)平衡二叉树,但是为了保持“平衡”是需要付出代价的,红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,这费事啊。你说说我们引入红黑树就是为了查找数据快,如果链表长度很短的话,根本不需要引入红黑树的,你引入之后还要付出代价维持它的平衡。但是链表过长就不一样了。至于为什么选 8 这个值呢?通过概率统计所得,这个值是综合查询成本和新增元素成本得出的最好的一个值。
@ -676,12 +659,10 @@ hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返
#### 1.2.2 为什么要有 hashCode #### 1.2.2 为什么要有 hashCode
**我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode** **我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode**
当你把对象加入 HashSet 时HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的 hashcodeHashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals方法来检查 hashcode 相等的对象是否真的相同。如果两者相同HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的 Java 启蒙书《Head fist java》第二版。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。 当你把对象加入 HashSet 时HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的 hashcodeHashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals方法来检查 hashcode 相等的对象是否真的相同。如果两者相同HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的 Java 启蒙书《Head fist java》第二版。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。
#### 1.2.3 hashCode()与 equals()的相关规定 #### 1.2.3 hashCode()与 equals()的相关规定
1. 如果两个对象相等,则 hashcode 一定也是相同的 1. 如果两个对象相等,则 hashcode 一定也是相同的
@ -709,7 +690,6 @@ hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返
- 情况 1类没有覆盖 equals()方法。则通过 equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。 - 情况 1类没有覆盖 equals()方法。则通过 equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
- 情况 2类覆盖了 equals()方法。一般,我们都覆盖 equals()方法来两个对象的内容相等;若它们的内容相等,则返回 true(即,认为这两个对象相等)。 - 情况 2类覆盖了 equals()方法。一般,我们都覆盖 equals()方法来两个对象的内容相等;若它们的内容相等,则返回 true(即,认为这两个对象相等)。
**举个例子:** **举个例子:**
```java ```java
@ -808,10 +788,8 @@ synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团
在 JDK1.6 之前synchronized 的性能是比 ReentrantLock 差很多。具体表示为synchronized 关键字吞吐量岁线程数的增加,下降得非常严重。而 ReentrantLock 基本保持一个比较稳定的水平。我觉得这也侧面反映了, synchronized 关键字还有非常大的优化余地。后续的技术发展也证明了这一点,我们上面也讲了在 JDK1.6 之后 JVM 团队对 synchronized 关键字做了很多优化。JDK1.6 之后synchronized 和 ReentrantLock 的性能基本是持平了。所以网上那些说因为性能才选择 ReentrantLock 的文章都是错的JDK1.6 之后,性能已经不是选择 synchronized 和 ReentrantLock 的影响因素了!而且虚拟机在未来的性能改进中会更偏向于原生的 synchronized所以还是提倡在 synchronized 能满足你的需求的情况下,优先考虑使用 synchronized 关键字来进行同步!优化后的 synchronized 和 ReentrantLock 一样,在很多地方都是用到了 CAS 操作。 在 JDK1.6 之前synchronized 的性能是比 ReentrantLock 差很多。具体表示为synchronized 关键字吞吐量岁线程数的增加,下降得非常严重。而 ReentrantLock 基本保持一个比较稳定的水平。我觉得这也侧面反映了, synchronized 关键字还有非常大的优化余地。后续的技术发展也证明了这一点,我们上面也讲了在 JDK1.6 之后 JVM 团队对 synchronized 关键字做了很多优化。JDK1.6 之后synchronized 和 ReentrantLock 的性能基本是持平了。所以网上那些说因为性能才选择 ReentrantLock 的文章都是错的JDK1.6 之后,性能已经不是选择 synchronized 和 ReentrantLock 的影响因素了!而且虚拟机在未来的性能改进中会更偏向于原生的 synchronized所以还是提倡在 synchronized 能满足你的需求的情况下,优先考虑使用 synchronized 关键字来进行同步!优化后的 synchronized 和 ReentrantLock 一样,在很多地方都是用到了 CAS 操作。
## 4 线程池了解吗? ## 4 线程池了解吗?
### 4.1 为什么要用线程池? ### 4.1 为什么要用线程池?
线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。
@ -852,8 +830,8 @@ FixedThreadPool 和 SingleThreadExecutor 允许请求的队列长度为 Inte
CachedThreadPool 和 ScheduledThreadPool 允许创建的线程数量为 Integer.MAX_VALUE 可能会创建大量线程从而导致OOM。 CachedThreadPool 和 ScheduledThreadPool 允许创建的线程数量为 Integer.MAX_VALUE 可能会创建大量线程从而导致OOM。
``` ```
**2 ThreadPoolExecutor的构造函数创建**
**2 ThreadPoolExecutor 的构造函数创建**
我们可以自己直接调用 ThreadPoolExecutor 的构造函数来自己创建线程池。在创建的同时,给 BlockQueue 指定容量就可以了。示例如下: 我们可以自己直接调用 ThreadPoolExecutor 的构造函数来自己创建线程池。在创建的同时,给 BlockQueue 指定容量就可以了。示例如下:
@ -925,7 +903,7 @@ Nginx支持的weight轮询默认、ip_hash、fair、url_hash这四种负
### 5.2 为什么要用 Nginx? ### 5.2 为什么要用 Nginx?
> 这部分内容参考极客时间—[Nginx核心知识100讲的内容](https://time.geekbang.org/course/intro/138?code=AycjiiQk6uQRxnVJzBupFkrGkvZlmYELPRsZbWzaAHE=)。 > 这部分内容参考极客时间—[Nginx 核心知识 100 讲的内容](https://time.geekbang.org/course/intro/138?code=AycjiiQk6uQRxnVJzBupFkrGkvZlmYELPRsZbWzaAHE= "Nginx核心知识100讲的内容")。
如果面试官问你这个问题,就一定想看你知道 Nginx 服务器的一些优点吗。 如果面试官问你这个问题,就一定想看你知道 Nginx 服务器的一些优点吗。
@ -939,7 +917,7 @@ Nginx 有以下5个优点
### 5.3 Nginx 的四个主要组成部分了解吗? ### 5.3 Nginx 的四个主要组成部分了解吗?
> 这部分内容参考极客时间—[Nginx核心知识100讲的内容](https://time.geekbang.org/course/intro/138?code=AycjiiQk6uQRxnVJzBupFkrGkvZlmYELPRsZbWzaAHE=)。 > 这部分内容参考极客时间—[Nginx 核心知识 100 讲的内容](https://time.geekbang.org/course/intro/138?code=AycjiiQk6uQRxnVJzBupFkrGkvZlmYELPRsZbWzaAHE= "Nginx核心知识100讲的内容")。
- Nginx 二进制可执行文件:由各模块源码编译出一个文件 - Nginx 二进制可执行文件:由各模块源码编译出一个文件
- nginx.conf 配置文件:控制 Nginx 行为 - nginx.conf 配置文件:控制 Nginx 行为