1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-08-10 00:41:37 +08:00

Fix 标题格式错误导致目录链接失效

This commit is contained in:
SnailClimb 2019-03-03 16:51:36 +08:00 committed by GitHub
parent ad574052d4
commit 9c7ab2d684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,9 +1,82 @@
<!-- MarkdownTOC -->
- [一 基础篇](#一-基础篇)
- [1. `System.out.println(3|9)`输出什么?](#1-systemoutprintln3|9输出什么)
- [2. 说一下转发\(Forward\)和重定向\(Redirect\)的区别](#2-说一下转发forward和重定向redirect的区别)
- [3. 在浏览器中输入url地址到显示主页的过程,整个过程会使用哪些协议](#3-在浏览器中输入url地址到显示主页的过程整个过程会使用哪些协议)
- [4. TCP 三次握手和四次挥手](#4-tcp-三次握手和四次挥手)
- [为什么要三次握手](#为什么要三次握手)
- [为什么要传回 SYN](#为什么要传回-syn)
- [传了 SYN,为啥还要传 ACK](#传了-syn为啥还要传-ack)
- [为什么要四次挥手](#为什么要四次挥手)
- [5. IP地址与MAC地址的区别](#5-ip地址与mac地址的区别)
- [6. HTTP请求,响应报文格式](#6-http请求响应报文格式)
- [7. 为什么要使用索引?索引这么多优点,为什么不对表中的每一个列创建一个索引呢?索引是如何提高查询速度的?说一下使用索引的注意事项?Mysql索引主要使用的两种数据结构?什么是覆盖索引?](#7-为什么要使用索引索引这么多优点为什么不对表中的每一个列创建一个索引呢索引是如何提高查询速度的说一下使用索引的注意事项mysql索引主要使用的两种数据结构什么是覆盖索引)
- [8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不?](#8-进程与线程的区别是什么进程间的几种通信方式说一下线程间的几种通信方式知道不)
- [9. 为什么要用单例模式?手写几种线程安全的单例模式?](#9-为什么要用单例模式手写几种线程安全的单例模式)
- [10. 简单介绍一下bean;知道Spring的bean的作用域与生命周期吗?](#10-简单介绍一下bean知道spring的bean的作用域与生命周期吗)
- [11. Spring 中的事务传播行为了解吗?TransactionDefinition 接口中哪五个表示隔离级别的常量?](#11-spring-中的事务传播行为了解吗transactiondefinition-接口中哪五个表示隔离级别的常量)
- [事务传播行为](#事务传播行为)
- [隔离级别](#隔离级别)
- [12. SpringMVC 原理了解吗?](#12-springmvc-原理了解吗)
- [13. Spring AOP IOC 实现原理](#13-spring-aop-ioc-实现原理)
- [二 进阶篇](#二-进阶篇)
- [1 消息队列MQ的套路](#1-消息队列mq的套路)
- [1.1 介绍一下消息队列MQ的应用场景/使用消息队列的好处](#11-介绍一下消息队列mq的应用场景使用消息队列的好处)
- [1)通过异步处理提高系统性能](#1通过异步处理提高系统性能)
- [2)降低系统耦合性](#2降低系统耦合性)
- [1.2 那么使用消息队列会带来什么问题?考虑过这些问题吗?](#12-那么使用消息队列会带来什么问题考虑过这些问题吗)
- [1.3 介绍一下你知道哪几种消息队列,该如何选择呢?](#13-介绍一下你知道哪几种消息队列该如何选择呢)
- [1.4 关于消息队列其他一些常见的问题展望](#14-关于消息队列其他一些常见的问题展望)
- [2 谈谈 InnoDB 和 MyIsam 两者的区别](#2-谈谈-innodb-和-myisam-两者的区别)
- [2.1 两者的对比](#21-两者的对比)
- [2.2 关于两者的总结](#22-关于两者的总结)
- [3 聊聊 Java 中的集合吧!](#3-聊聊-java-中的集合吧!)
- [3.1 Arraylist 与 LinkedList 有什么不同?\(注意加上从数据结构分析的内容\)](#31-arraylist-与-linkedlist-有什么不同注意加上从数据结构分析的内容)
- [3.2 HashMap的底层实现](#32-hashmap的底层实现)
- [1)JDK1.8之前](#1jdk18之前)
- [2)JDK1.8之后](#2jdk18之后)
- [3.3 既然谈到了红黑树,你给我手绘一个出来吧,然后简单讲一下自己对于红黑树的理解](#33-既然谈到了红黑树你给我手绘一个出来吧然后简单讲一下自己对于红黑树的理解)
- [3.4 红黑树这么优秀,为何不直接使用红黑树得了?](#34-红黑树这么优秀为何不直接使用红黑树得了)
- [3.5 HashMap 和 Hashtable 的区别/HashSet 和 HashMap 区别](#35-hashmap-和-hashtable-的区别hashset-和-hashmap-区别)
- [三 终结篇](#三-终结篇)
- [1. Object类有哪些方法?](#1-object类有哪些方法)
- [1.1 Object类的常见方法总结](#11-object类的常见方法总结)
- [1.2 hashCode与equals](#12-hashcode与equals)
- [1.2.1 hashCode\(\)介绍](#121-hashcode介绍)
- [1.2.2 为什么要有hashCode](#122-为什么要有hashcode)
- [1.2.3 hashCode\(\)与equals\(\)的相关规定](#123-hashcode与equals的相关规定)
- [1.2.4 为什么两个对象有相同的hashcode值,它们也不一定是相等的?](#124-为什么两个对象有相同的hashcode值它们也不一定是相等的)
- [1.3 ==与equals](#13-与equals)
- [2 ConcurrentHashMap 相关问题](#2-concurrenthashmap-相关问题)
- [2.1 ConcurrentHashMap 和 Hashtable 的区别](#21-concurrenthashmap-和-hashtable-的区别)
- [2.2 ConcurrentHashMap线程安全的具体实现方式/底层具体实现](#22-concurrenthashmap线程安全的具体实现方式底层具体实现)
- [JDK1.7\(上面有示意图\)](#jdk17上面有示意图)
- [JDK1.8\(上面有示意图\)](#jdk18上面有示意图)
- [3 谈谈 synchronized 和 ReenTrantLock 的区别](#3-谈谈-synchronized-和-reentrantlock-的区别)
- [4 线程池了解吗?](#4-线程池了解吗)
- [4.1 为什么要用线程池?](#41-为什么要用线程池)
- [4.2 Java 提供了哪几种线程池?他们各自的使用场景是什么?](#42-java-提供了哪几种线程池他们各自的使用场景是什么)
- [Java 主要提供了下面4种线程池](#java-主要提供了下面4种线程池)
- [各种线程池的适用场景介绍](#各种线程池的适用场景介绍)
- [4.3 创建的线程池的方式](#43-创建的线程池的方式)
- [5 Nginx](#5-nginx)
- [5.1 简单介绍一下Nginx](#51-简单介绍一下nginx)
- [反向代理](#反向代理)
- [负载均衡](#负载均衡)
- [动静分离](#动静分离)
- [5.2 为什么要用 Nginx?](#52-为什么要用-nginx)
- [5.3 Nginx 的四个主要组成部分了解吗?](#53-nginx-的四个主要组成部分了解吗)
<!-- /MarkdownTOC -->
这些问题是2018年去美团面试的同学被问到的一些常见的问题希望对你有帮助 这些问题是2018年去美团面试的同学被问到的一些常见的问题希望对你有帮助
# 一 基础篇 # 一 基础篇
## 1. `System.out.println(3 | 9);`输出什么? ## 1. `System.out.println(3|9)`输出什么?
正确答案11. 正确答案11.
@ -140,7 +213,7 @@ 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)
## 7. 为什么要使用索引索引这么多优点为什么不对表中的每一个列创建一个索引呢索引是如何提高查询速度的说一下使用索引的注意事项Mysql索引主要使用的两种数据结构什么是覆盖索引? ## 7. 为什么要使用索引?索引这么多优点,为什么不对表中的每一个列创建一个索引呢?索引是如何提高查询速度的?说一下使用索引的注意事项?Mysql索引主要使用的两种数据结构?什么是覆盖索引?
**为什么要使用索引?** **为什么要使用索引?**
@ -181,7 +254,7 @@ HTTP响应报文主要由状态行、响应头部、响应正文3部分组成
之为“覆盖索引”。我们知道在InnoDB存储引擎中如果不是主键索引叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次,这样就会比较慢。覆盖索引就是把要查询出的列和索引是对应的,不做回表操作! 之为“覆盖索引”。我们知道在InnoDB存储引擎中如果不是主键索引叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次,这样就会比较慢。覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!
## 8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不? ## 8. 进程与线程的区别是什么?进程间的几种通信方式说一下?线程间的几种通信方式知道不?
**进程与线程的区别是什么?** **进程与线程的区别是什么?**
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。另外,也正是因为共享资源,所以线程中执行时一般都要进行同步和互斥。总的来说,进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。另外,也正是因为共享资源,所以线程中执行时一般都要进行同步和互斥。总的来说,进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
@ -210,7 +283,7 @@ HTTP响应报文主要由状态行、响应头部、响应正文3部分组成
线程间通信的主要目的是用于线程同步,所以线程没有象进程通信中用于数据交换的通信机制。 线程间通信的主要目的是用于线程同步,所以线程没有象进程通信中用于数据交换的通信机制。
## 9. 为什么要用单例模式?手写几种线程安全的单例模式? ## 9. 为什么要用单例模式?手写几种线程安全的单例模式?
**简单来说使用单例模式可以带来下面几个好处:** **简单来说使用单例模式可以带来下面几个好处:**
@ -260,7 +333,7 @@ public class Singleton {
} }
``` ```
## 10. 简单介绍一下bean。知道Spring的bean的作用域与生命周期吗 ## 10. 简单介绍一下bean;知道Spring的bean的作用域与生命周期吗?
在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean。简单地讲bean 就是由 IOC 容器初始化、装配及管理的对象除此之外bean 就与应用程序中的其他对象没有什么区别了。而 bean 的定义以及 bean 相互间的依赖关系将通过配置元数据来描述。 在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean。简单地讲bean 就是由 IOC 容器初始化、装配及管理的对象除此之外bean 就与应用程序中的其他对象没有什么区别了。而 bean 的定义以及 bean 相互间的依赖关系将通过配置元数据来描述。
@ -271,7 +344,7 @@ 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 接口中哪五个表示隔离级别的常量?
#### 事务传播行为 #### 事务传播行为
@ -305,7 +378,7 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
- **TransactionDefinition.ISOLATION_REPEATABLE_READ:** 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 - **TransactionDefinition.ISOLATION_REPEATABLE_READ:** 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- **TransactionDefinition.ISOLATION_SERIALIZABLE:** 最高的隔离级别完全服从ACID的隔离级别。所有的事务依次逐个执行这样事务之间就完全不可能产生干扰也就是说该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 - **TransactionDefinition.ISOLATION_SERIALIZABLE:** 最高的隔离级别完全服从ACID的隔离级别。所有的事务依次逐个执行这样事务之间就完全不可能产生干扰也就是说该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
## 12. SpringMVC 原理了解吗 ## 12. SpringMVC 原理了解吗?
![SpringMVC 原理](https://user-gold-cdn.xitu.io/2018/11/10/166fd45787394192?w=1015&h=466&f=webp&s=35352) ![SpringMVC 原理](https://user-gold-cdn.xitu.io/2018/11/10/166fd45787394192?w=1015&h=466&f=webp&s=35352)
@ -325,17 +398,17 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
# 二 进阶篇 # 二 进阶篇
# 1 消息队列MQ的套路 ## 1 消息队列MQ的套路
消息队列/消息中间件应该是Java程序员必备的一个技能了如果你之前没接触过消息队列的话建议先去百度一下某某消息队列入门然后花2个小时就差不多可以学会任何一种消息队列的使用了。如果说仅仅学会使用是万万不够的在实际生产环境还要考虑消息丢失等等情况。关于消息队列面试相关的问题推荐大家也可以看一下视频《Java工程师面试突击第1季-中华石杉老师》如果大家没有资源的话可以在我的公众号“Java面试通关手册”后台回复关键字“1”即可 消息队列/消息中间件应该是Java程序员必备的一个技能了如果你之前没接触过消息队列的话建议先去百度一下某某消息队列入门然后花2个小时就差不多可以学会任何一种消息队列的使用了。如果说仅仅学会使用是万万不够的在实际生产环境还要考虑消息丢失等等情况。关于消息队列面试相关的问题推荐大家也可以看一下视频《Java工程师面试突击第1季-中华石杉老师》如果大家没有资源的话可以在我的公众号“Java面试通关手册”后台回复关键字“1”即可
### 1.1 介绍一下消息队列MQ的应用场景/使用消息队列的好处 ### 1.1 介绍一下消息队列MQ的应用场景/使用消息队列的好处
面试官一般会先问你这个问题预热一下看你知道消息队列不一般在第一面的时候面试官可能只会问消息队列MQ的应用场景/使用消息队列的好处、使用消息队列会带来什么问题、消息队列的技术选型这几个问题,不会太深究下去,在后面的第二轮/第三轮技术面试中可能会深入问一下。 面试官一般会先问你这个问题预热一下看你知道消息队列不一般在第一面的时候面试官可能只会问消息队列MQ的应用场景/使用消息队列的好处、使用消息队列会带来什么问题、消息队列的技术选型这几个问题,不会太深究下去,在后面的第二轮/第三轮技术面试中可能会深入问一下。
**《大型网站技术架构》第四章和第七章均有提到消息队列对应用性能及扩展性的提升。** **《大型网站技术架构》第四章和第七章均有提到消息队列对应用性能及扩展性的提升。**
#### ①.通过异步处理提高系统性能 #### 1)通过异步处理提高系统性能
![通过异步处理提高系统性能](https://user-gold-cdn.xitu.io/2018/4/21/162e63a8e34ba534?w=910&h=350&f=jpeg&s=29123) ![通过异步处理提高系统性能](https://user-gold-cdn.xitu.io/2018/4/21/162e63a8e34ba534?w=910&h=350&f=jpeg&s=29123)
如上图,**在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。** 如上图,**在不使用消息队列服务器的时候,用户的请求数据直接写入数据库,在高并发的情况下数据库压力剧增,使得响应速度变慢。但是在使用消息队列之后,用户的请求数据发送给消息队列之后立即 返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器处理速度快于数据库(消息队列也比数据库有更好的伸缩性),因此响应速度得到大幅改善。**
@ -343,7 +416,7 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
![合理使用消息队列可以有效抵御促销活动刚开始大量订单涌入对系统的冲击](https://user-gold-cdn.xitu.io/2018/4/21/162e64583dd3ed01?w=780&h=384&f=jpeg&s=13550) ![合理使用消息队列可以有效抵御促销活动刚开始大量订单涌入对系统的冲击](https://user-gold-cdn.xitu.io/2018/4/21/162e64583dd3ed01?w=780&h=384&f=jpeg&s=13550)
因为**用户请求数据写入消息队列之后就立即返回给用户了,但是请求数据在后续的业务校验、写数据库等操作中可能失败**。因此使用消息队列进行异步处理之后,需要**适当修改业务流程进行配合**,比如**用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功**,以免交易纠纷。这就类似我们平时手机订火车票和电影票。 因为**用户请求数据写入消息队列之后就立即返回给用户了,但是请求数据在后续的业务校验、写数据库等操作中可能失败**。因此使用消息队列进行异步处理之后,需要**适当修改业务流程进行配合**,比如**用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功**,以免交易纠纷。这就类似我们平时手机订火车票和电影票。
### ②.降低系统耦合性 #### 2)降低系统耦合性
我们知道模块分布式部署以后聚合方式通常有两种1.**分布式消息队列**和2.**分布式服务**。 我们知道模块分布式部署以后聚合方式通常有两种1.**分布式消息队列**和2.**分布式服务**。
> **先来简单说一下分布式服务:** > **先来简单说一下分布式服务:**
@ -366,7 +439,7 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
> 这个问题一般会在上一个问题问完之后,紧接着被问到。“使用消息队列会带来什么问题?”这个问题要引起重视,一般我们都会考虑使用消息队列会带来的好处而忽略它带来的问题! > 这个问题一般会在上一个问题问完之后,紧接着被问到。“使用消息队列会带来什么问题?”这个问题要引起重视,一般我们都会考虑使用消息队列会带来的好处而忽略它带来的问题!
### 1.2 那么使用消息队列会带来什么问题?考虑过这个问题吗? ### 1.2 那么使用消息队列会带来什么问题?考虑过这些问题吗?
- **系统可用性降低:** 系统可用性在某种程度上降低为什么这样说呢在加入MQ之前你不用考虑消息丢失或者说MQ挂掉等等的情况但是引入MQ之后你就需要去考虑了 - **系统可用性降低:** 系统可用性在某种程度上降低为什么这样说呢在加入MQ之前你不用考虑消息丢失或者说MQ挂掉等等的情况但是引入MQ之后你就需要去考虑了
- **系统复杂性提高:** 加入MQ之后你需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题 - **系统复杂性提高:** 加入MQ之后你需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题
@ -374,7 +447,7 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
> 了解下面这个问题是为了我们更好的进行技术选型该部分摘自《Java工程师面试突击第1季-中华石杉老师》如果大家没有资源的话可以在我的公众号“Java面试通关手册”后台回复关键字“1”即可 > 了解下面这个问题是为了我们更好的进行技术选型该部分摘自《Java工程师面试突击第1季-中华石杉老师》如果大家没有资源的话可以在我的公众号“Java面试通关手册”后台回复关键字“1”即可
### 1.3 介绍一下你知道哪几种消息队列,该如何选择呢? ### 1.3 介绍一下你知道哪几种消息队列,该如何选择呢?
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafaka | | 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafaka |
@ -404,12 +477,9 @@ TransactionDefinition 接口中定义了五个表示隔离级别的常量:
### 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 关于两者的总结
@ -421,8 +491,7 @@ MyISAM更适合读密集的表而InnoDB更适合写密集的的表。 在数
## 3 聊聊 Java 中的集合吧! ## 3 聊聊 Java 中的集合吧!
### 3.1 Arraylist 与 LinkedList 有什么不同?(注意加上从数据结构分析的内容)
### 3.1 Arraylist 与 LinkedList 有什么不同?(注意加上从数据结构分析的内容)
- **1. 是否保证线程安全:** ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; - **1. 是否保证线程安全:** ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;
- **2. 底层数据结构:** Arraylist 底层使用的是Object数组LinkedList 底层使用的是双向链表数据结构(注意双向链表和双向循环链表的区别:); - **2. 底层数据结构:** Arraylist 底层使用的是Object数组LinkedList 底层使用的是双向链表数据结构(注意双向链表和双向循环链表的区别:);
@ -464,7 +533,7 @@ ArraysList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什
### 3.2 HashMap的底层实现 ### 3.2 HashMap的底层实现
#### JDK1.8之前 #### 1)JDK1.8之前
JDK1.8 之前 HashMap 底层是 **数组和链表** 结合在一起使用也就是 **链表散列**。**HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 `(n - 1) & hash` 判断当前元素存放的位置(这里的 n 指的时数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。** JDK1.8 之前 HashMap 底层是 **数组和链表** 结合在一起使用也就是 **链表散列**。**HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 `(n - 1) & hash` 判断当前元素存放的位置(这里的 n 指的时数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。**
@ -505,7 +574,7 @@ static int hash(int h) {
![jdk1.8之前的内部结构](https://user-gold-cdn.xitu.io/2018/3/20/16240dbcc303d872?w=348&h=427&f=png&s=10991) ![jdk1.8之前的内部结构](https://user-gold-cdn.xitu.io/2018/3/20/16240dbcc303d872?w=348&h=427&f=png&s=10991)
#### JDK1.8之后 #### 2)JDK1.8之后
相比于之前的版本, JDK1.8之后在解决哈希冲突时有了较大的变化当链表长度大于阈值默认为8将链表转化为红黑树以减少搜索时间。 相比于之前的版本, JDK1.8之后在解决哈希冲突时有了较大的变化当链表长度大于阈值默认为8将链表转化为红黑树以减少搜索时间。
@ -515,7 +584,7 @@ TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红
> 问完 HashMap 的底层原理之后,面试官可能就会紧接着问你 HashMap 底层数据结构相关的问题! > 问完 HashMap 的底层原理之后,面试官可能就会紧接着问你 HashMap 底层数据结构相关的问题!
### 3.3 既然谈到了红黑树,你给我手绘一个出来吧,然后简单讲一下自己对于红黑树的理解 ### 3.3 既然谈到了红黑树,你给我手绘一个出来吧,然后简单讲一下自己对于红黑树的理解
![红黑树](https://user-gold-cdn.xitu.io/2018/11/14/16711ac29c138cba?w=851&h=614&f=jpeg&s=34458) ![红黑树](https://user-gold-cdn.xitu.io/2018/11/14/16711ac29c138cba?w=851&h=614&f=jpeg&s=34458)
@ -537,11 +606,11 @@ TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。
简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。 简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
### 3.4 红黑树这么优秀,为何不直接使用红黑树得了? ### 3.4 红黑树这么优秀,为何不直接使用红黑树得了?
说一下自己对于这个问题的看法:我们知道红黑树属于(自)平衡二叉树,但是为了保持“平衡”是需要付出代价的,红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,这费事啊。你说说我们引入红黑树就是为了查找数据快,如果链表长度很短的话,根本不需要引入红黑树的,你引入之后还要付出代价维持它的平衡。但是链表过长就不一样了。至于为什么选 8 这个值呢?通过概率统计所得,这个值是综合查询成本和新增元素成本得出的最好的一个值。 说一下自己对于这个问题的看法:我们知道红黑树属于(自)平衡二叉树,但是为了保持“平衡”是需要付出代价的,红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,这费事啊。你说说我们引入红黑树就是为了查找数据快,如果链表长度很短的话,根本不需要引入红黑树的,你引入之后还要付出代价维持它的平衡。但是链表过长就不一样了。至于为什么选 8 这个值呢?通过概率统计所得,这个值是综合查询成本和新增元素成本得出的最好的一个值。
### 3.5 HashMap 和 Hashtable 的区别/HashSet 和 HashMap 区别 ### 3.5 HashMap 和 Hashtable 的区别/HashSet 和 HashMap 区别
**HashMap 和 Hashtable 的区别** **HashMap 和 Hashtable 的区别**
@ -598,7 +667,7 @@ protected void finalize() throws Throwable { }//实例被垃圾回收器回收
面试官可能会问你:“你重写过 hashcode 和 equals 么为什么重写equals时必须重写hashCode方法 面试官可能会问你:“你重写过 hashcode 和 equals 么为什么重写equals时必须重写hashCode方法
#### 1.2.1 hashCode介绍 #### 1.2.1 hashCode()介绍
hashCode() 的作用是获取哈希码也称为散列码它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中这就意味着Java中的任何类都包含有hashCode() 函数。另外需要注意的是: Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法通常用来将对象的 内存地址 转换为整数之后返回。 hashCode() 的作用是获取哈希码也称为散列码它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中这就意味着Java中的任何类都包含有hashCode() 函数。另外需要注意的是: Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法通常用来将对象的 内存地址 转换为整数之后返回。
@ -616,7 +685,7 @@ 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一定也是相同的
2. 两个对象相等,对两个对象分别调用equals方法都返回true 2. 两个对象相等,对两个对象分别调用equals方法都返回true
@ -624,7 +693,7 @@ hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返
4. **因此equals方法被覆盖过则hashCode方法也必须被覆盖** 4. **因此equals方法被覆盖过则hashCode方法也必须被覆盖**
5. hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode()则该class的两个对象无论如何都不会相等即使这两个对象指向相同的数据 5. hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode()则该class的两个对象无论如何都不会相等即使这两个对象指向相同的数据
#### 1.2.4 为什么两个对象有相同的hashcode值,它们也不一定是相等的? #### 1.2.4 为什么两个对象有相同的hashcode值,它们也不一定是相等的?
在这里解释一位小伙伴的问题。以下内容摘自《Head Fisrt Java》。 在这里解释一位小伙伴的问题。以下内容摘自《Head Fisrt Java》。
@ -675,7 +744,7 @@ public class test1 {
## 2 ConcurrentHashMap 相关问题 ## 2 ConcurrentHashMap 相关问题
### 2.1 ConcurrentHashMap 和 Hashtable 的区别 ### 2.1 ConcurrentHashMap 和 Hashtable 的区别
ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。 ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。
@ -697,7 +766,7 @@ Node: 链表节点):
### 2.2 ConcurrentHashMap线程安全的具体实现方式/底层具体实现 ### 2.2 ConcurrentHashMap线程安全的具体实现方式/底层具体实现
#### JDK1.7(上面有示意图) #### JDK1.7(上面有示意图)
首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。
@ -712,7 +781,7 @@ static class Segment<K,V> extends ReentrantLock implements Serializable {
一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似是一种数组和链表结构一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。 一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似是一种数组和链表结构一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。
#### JDK1.8 (上面有示意图) #### JDK1.8(上面有示意图)
ConcurrentHashMap取消了Segment分段锁采用CAS和synchronized来保证并发安全。数据结构跟HashMap1.8的结构类似,数组+链表/红黑二叉树。 ConcurrentHashMap取消了Segment分段锁采用CAS和synchronized来保证并发安全。数据结构跟HashMap1.8的结构类似,数组+链表/红黑二叉树。
@ -743,10 +812,10 @@ 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 为什么要用线程池?
线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。
@ -756,7 +825,7 @@ synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团
- **提高响应速度。** 当任务到达时,任务可以不需要的等到线程创建就能立即执行。 - **提高响应速度。** 当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- **提高线程的可管理性。** 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。 - **提高线程的可管理性。** 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
### 4.2 Java 提供了哪几种线程池?他们各自的使用场景是什么? ### 4.2 Java 提供了哪几种线程池?他们各自的使用场景是什么?
#### Java 主要提供了下面4种线程池 #### Java 主要提供了下面4种线程池
@ -857,7 +926,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=)。
@ -871,11 +940,11 @@ Nginx 有以下5个优点
4. 热部署(这个功能对于 Nginx 来说特别重要,热部署指可以在不停止 Nginx服务的情况下升级 Nginx 4. 热部署(这个功能对于 Nginx 来说特别重要,热部署指可以在不停止 Nginx服务的情况下升级 Nginx
5. BSD许可证意味着我们可以将源代码下载下来进行修改然后使用自己的版本 5. BSD许可证意味着我们可以将源代码下载下来进行修改然后使用自己的版本
### 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 二进制可执行文件:由各模块源码编译出一个文件 - Nginx 二进制可执行文件:由各模块源码编译出一个文件
- Nginx.conf 配置文件控制Nginx 行为 - Nginx.conf 配置文件控制Nginx 行为
- acess.log 访问日志: 记录每一条HTTP请求信息 - acess.log 访问日志: 记录每一条HTTP请求信息
- error.log 错误日志:定位问题 - error.log 错误日志:定位问题