From c14676e387316d83da7be75e53ba571b9f6b129e Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 30 May 2019 12:30:56 +0800
Subject: [PATCH 01/25] Create SpringInterviewQuestions.md
---
.../spring/SpringInterviewQuestions.md | 291 ++++++++++++++++++
1 file changed, 291 insertions(+)
create mode 100644 docs/system-design/framework/spring/SpringInterviewQuestions.md
diff --git a/docs/system-design/framework/spring/SpringInterviewQuestions.md b/docs/system-design/framework/spring/SpringInterviewQuestions.md
new file mode 100644
index 00000000000..b214ff502ed
--- /dev/null
+++ b/docs/system-design/framework/spring/SpringInterviewQuestions.md
@@ -0,0 +1,291 @@
+
+
+- [什么是 Spring 框架?](#什么是-spring-框架)
+- [列举一些重要的Spring模块?](#列举一些重要的spring模块)
+- [谈谈自己对于 Spring IoC 和 AOP 的理解](#谈谈自己对于-spring-ioc-和-aop-的理解)
+- [Spring AOP 和 AspectJ AOP 有什么区别?](#spring-aop-和-aspectj-aop-有什么区别)
+- [Spring 中的 bean 的作用域有哪些?](#spring-中的-bean-的作用域有哪些)
+- [Spring 中的单例 bean 的线程安全问题了解吗?](#spring-中的单例-bean-的线程安全问题了解吗)
+- [Spring 中的 bean 生命周期?](#spring-中的-bean-生命周期)
+- [说说自己对于 Spring MVC 了解?](#说说自己对于-spring-mvc-了解)
+- [SpringMVC 工作原理了解吗?](#springmvc-工作原理了解吗)
+- [Spring 框架中用到了哪些设计模式?](#spring-框架中用到了哪些设计模式)
+- [@Component 和 @Bean 的区别是什么?](#component-和-bean-的区别是什么)
+- [将一个类声明为Spring的 bean 的注解有哪些?](#将一个类声明为spring的-bean-的注解有哪些)
+- [Spring 管理事务的方式有几种?](#spring-管理事务的方式有几种)
+- [Spring 事务中的隔离级别有哪几种?](#spring-事务中的隔离级别有哪几种)
+- [Spring 事务中哪几种事务传播行为?](#spring-事务中哪几种事务传播行为)
+- [参考](#参考)
+
+
+
+这篇文章主要是想通过一些问题,加深大家对于 Spring 的理解,所以不会涉及太多的代码!这篇文章整理了挺长时间,下面的很多问题我自己在使用 Spring 的过程中也并没有注意,自己也是临时查阅了很多资料和书籍补上的。网上也有一些很多关于 Spring 常见问题/面试题整理的文章,我感觉大部分都是互相 copy,而且很多问题也不是很汗,有些回答也存在问题。所以,自己花了一周的业余时间整理了一下,希望对大家有帮助。
+
+## 什么是 Spring 框架?
+
+Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。Spring 官网:。
+
+我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:Core Container 中的 Core 组件是Spring 所有组件的核心,Beans 组件和 Context 组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。
+
+Spring 官网列出的 Spring 的 6 个特征:
+
+- **核心技术** :依赖注入(DI),AOP,事件(events),资源,i18n,验证,数据绑定,类型转换,SpEL。
+- **测试** :模拟对象,TestContext框架,Spring MVC 测试,WebTestClient。
+- **数据访问** :事务,DAO支持,JDBC,ORM,编组XML。
+- **Web支持** : Spring MVC和Spring WebFlux Web框架。
+- **集成** :远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。
+- **语言** :Kotlin,Groovy,动态语言。
+
+## 列举一些重要的Spring模块?
+
+下图对应的是 Spring4.x 版本。目前最新的5.x版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了用于异步响应式处理的 WebFlux 组件。
+
+
+
+- **Spring Core:** 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IOC 依赖注入功能。
+- **Spring Aspects ** : 该模块为与AspectJ的集成提供支持。
+- **Spring AOP** :提供了面向方面的编程实现。
+- **Spring JDBC** : Java数据库连接。
+- **Spring JMS** :Java消息服务。
+- **Spring ORM** : 用于支持Hibernate等ORM工具。
+- **Spring Web** : 为创建Web应用程序提供支持。
+- **Spring Test** : 提供了对 JUnit 和 TestNG 测试的支持。
+
+## 谈谈自己对于 Spring IoC 和 AOP 的理解
+
+### IoC
+
+IoC(Inverse of Control:控制反转)是一种**设计思想**,就是 **将原本在程序中手动创建对象的控制权,交由Spring框架来管理。** IoC 在其他语言中也有应用,并非 Spirng 特有。 **IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。**
+
+将对象之间的相互依赖关系交给 IOC 容器来管理,并由 IOC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 **IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。** 在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IOC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
+
+Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。
+
+推荐阅读:https://www.zhihu.com/question/23277575/answer/169698662
+
+**Spring IOC的初始化过程:**
+
+
+IOC源码阅读
+
+- https://javadoop.com/post/spring-ioc
+
+### AOP
+
+AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,**却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来**,便于**减少系统的重复代码**,**降低模块间的耦合度**,并**有利于未来的可拓展性和可维护性**。
+
+**Spring AOP就是基于动态代理的**,如果要代理的对象,实现了某个接口,那么Spring AOP会使用**JDK Proxy**,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用**Cglib** ,这时候Spring AOP会使用 **Cglib** 生成一个被代理对象的子类来作为代理,如下图所示:
+
+
+
+当然你也可以使用 AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。
+
+使用 AOP 之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样大大简化了代码量。我们需要增加新功能时也方便,这样也提高了系统扩展性。日志功能、事务管理等等场景都用到了 AOP 。
+
+## Spring AOP 和 AspectJ AOP 有什么区别?
+
+**Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。** Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
+
+ Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
+
+如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。
+
+## Spring 中的 bean 的作用域有哪些?
+
+- singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
+- prototype : 每次请求都会创建一个新的 bean 实例。
+- request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
+- session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
+- global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话
+
+## Spring 中的单例 bean 的线程安全问题了解吗?
+
+大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
+
+常见的有两种解决办法:
+
+1. 在Bean对象中尽量避免定义可变的成员变量(不太现实)。
+
+2. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
+
+## Spring 中的 bean 生命周期?
+
+这部分网上有很多文章都讲到了,下面的内容整理自: ,除了这篇文章,再推荐一篇很不错的文章 : 。
+
+- Bean 容器找到配置文件中 Spring Bean 的定义。
+- Bean 容器利用 Java Reflection API 创建一个Bean的实例。
+- 如果涉及到一些属性值 利用 `set()`方法设置一些属性值。
+- 如果 Bean 实现了 `BeanNameAware` 接口,调用 `setBeanName()`方法,传入Bean的名字。
+- 如果 Bean 实现了 `BeanClassLoaderAware` 接口,调用 `setBeanClassLoader()`方法,传入 `ClassLoader`对象的实例。
+- 如果Bean实现了 `BeanFactoryAware` 接口,调用 `setBeanClassLoader()`方法,传入 `ClassLoade` r对象的实例。
+- 与上面的类似,如果实现了其他 `*.Aware`接口,就调用相应的方法。
+- 如果有和加载这个 Bean 的 Spring 容器相关的 `BeanPostProcessor` 对象,执行`postProcessBeforeInitialization()` 方法
+- 如果Bean实现了`InitializingBean`接口,执行`afterPropertiesSet()`方法。
+- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
+- 如果有和加载这个 Bean的 Spring 容器相关的 `BeanPostProcessor` 对象,执行`postProcessAfterInitialization()` 方法
+- 当要销毁 Bean 的时候,如果 Bean 实现了 `DisposableBean` 接口,执行 `destroy()` 方法。
+- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
+
+图示:
+
+
+
+与之比较类似的中文版本:
+
+
+
+## 说说自己对于 Spring MVC 了解?
+
+谈到这个问题,我们不得不提提之前 Model1 和 Model2 这两个没有 Spring MVC 的时代。
+
+- **Model1 时代** : 很多学 Java 后端比较晚的朋友可能并没有接触过 Model1 模式下的 JavaWeb 应用开发。在 Model1 模式下,整个 Web 应用几乎全部用 JSP 页面组成,只用少量的 JavaBean 来处理数据库连接、访问等操作。这个模式下 JSP 即是控制层又是表现层。显而易见,这种模式存在很多问题。比如①将控制逻辑和表现逻辑混杂在一起,导致代码重用率极低;②前端和后端相互依赖,难以进行测试并且开发效率极低;
+- **Model2 时代** :学过 Servlet 并做过相关 Demo 的朋友应该了解“Java Bean(Model)+ JSP(View,)+Servlet(Controller) ”这种开发模式,这就是早期的 JavaWeb MVC 开发模式。Model:系统涉及的数据,也就是 dao 和 bean。View:展示模型中的数据,只是用来展示。Controller:处理用户请求都发送给 ,返回数据给 JSP 并展示给用户。
+
+Model2 模式下还存在很多问题,Model2的抽象和封装程度还远远不够,使用Model2进行开发时不可避免地会重复造轮子,这就大大降低了程序的可维护性和复用性。于是很多JavaWeb开发相关的 MVC 框架营运而生比如Struts2,但是 Struts2 比较笨重。随着 Spring 轻量级开发框架的流行,Spring 生态圈出现了 Spring MVC 框架, Spring MVC 是当前最优秀的 MVC 框架。相比于 Struts2 , Spring MVC 使用更加简单和方便,开发效率更高,并且 Spring MVC 运行速度更快。
+
+MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的Web层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。
+
+**Spring MVC 的简单原理图如下:**
+
+
+
+## SpringMVC 工作原理了解吗?
+
+**原理如下图所示:**
+
+
+上图的一个笔误的小问题:Spring MVC 的入口函数也就是前端控制器 `DispatcherServlet` 的作用是接收请求,响应结果。
+
+**流程说明(重要):**
+
+1. 客户端(浏览器)发送请求,直接请求到 `DispatcherServlet`。
+2. `DispatcherServlet` 根据请求信息调用 `HandlerMapping`,解析请求对应的 `Handler`。
+3. 解析到对应的 `Handler`(也就是我们平常说的 `Controller` 控制器)后,开始由 `HandlerAdapter` 适配器处理。
+4. `HandlerAdapter` 会根据 `Handler `来调用真正的处理器开处理请求,并处理相应的业务逻辑。
+5. 处理器处理完业务后,会返回一个 `ModelAndView` 对象,`Model` 是返回的数据对象,`View` 是个逻辑上的 `View`。
+6. `ViewResolver` 会根据逻辑 `View` 查找实际的 `View`。
+7. `DispaterServlet` 把返回的 `Model` 传给 `View`(视图渲染)。
+8. 把 `View` 返回给请求者(浏览器)
+
+## Spring 框架中用到了哪些设计模式?
+
+关于下面一些设计模式的详细介绍,可以看笔主前段时间的原创文章[《面试官:“谈谈Spring中都用到了那些设计模式?”。》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485303&idx=1&sn=9e4626a1e3f001f9b0d84a6fa0cff04a&chksm=cea248bcf9d5c1aaf48b67cc52bac74eb29d6037848d6cf213b0e5466f2d1fda970db700ba41&token=255050878&lang=zh_CN#rd) 。
+
+- **工厂设计模式** : Spring使用工厂模式通过 `BeanFactory`、`ApplicationContext` 创建 bean 对象。
+- **代理设计模式** : Spring AOP 功能的实现。
+- **单例设计模式** : Spring 中的 Bean 默认都是单例的。
+- **模板方法模式** : Spring 中 `jdbcTemplate`、`hibernateTemplate` 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
+- **包装器设计模式** : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
+- **观察者模式:** Spring 事件驱动模型就是观察者模式很经典的一个应用。
+- **适配器模式** :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配`Controller`。
+- ......
+
+## @Component 和 @Bean 的区别是什么?
+
+1. 作用对象不同: `@Component` 注解作用于类,而`@Bean`注解作用于方法。
+2. `@Component`通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用 `@ComponentScan` 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。`@Bean` 注解通常是我们在标有该注解的方法中定义产生这个 bean,`@Bean`告诉了Spring这是某个类的示例,当我需要用它的时候还给我。
+3. `@Bean` 注解比 `Component` 注解的自定义性更强,而且很多地方我们只能通过 `@Bean` 注解来注册bean。比如当我们引用第三方库中的类需要装配到 `Spring`容器时,则只能通过 `@Bean`来实现。
+
+`@Bean`注解使用示例:
+
+```java
+@Configuration
+public class AppConfig {
+ @Bean
+ public TransferService transferService() {
+ return new TransferServiceImpl();
+ }
+
+}
+```
+
+ 上面的代码相当于下面的 xml 配置
+
+```xml
+
+
+
+```
+
+下面这个例子是通过 `@Component` 无法实现的。
+
+```java
+@Bean
+public OneService getService(status) {
+ case (status) {
+ when 1:
+ return new serviceImpl1();
+ when 2:
+ return new serviceImpl2();
+ when 3:
+ return new serviceImpl3();
+ }
+}
+```
+
+## 将一个类声明为Spring的 bean 的注解有哪些?
+
+我们一般使用 `@Autowired` 注解自动装配 bean,要想把类标识成可用于 `@Autowired` 注解自动装配的 bean 的类,采用以下注解可实现:
+
+- `@Component` :通用的注解,可标注任意类为 `Spring` 组件。如果一个Bean不知道属于拿个层,可以使用`@Component` 注解标注。
+- `@Repository` : 对应持久层即 Dao 层,主要用于数据库相关操作。
+- `@Service` : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao层。
+- `@Controller` : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
+
+## Spring 管理事务的方式有几种?
+
+1. 编程式事务,在代码中硬编码。(不推荐使用)
+2. 声明式事务,在配置文件中配置(推荐使用)
+
+**声明式事务又分为两种:**
+
+1. 基于XML的声明式事务
+2. 基于注解的声明式事务
+
+## Spring 事务中的隔离级别有哪几种?
+
+**TransactionDefinition 接口中定义了五个表示隔离级别的常量:**
+
+- **TransactionDefinition.ISOLATION_DEFAULT:** 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
+- **TransactionDefinition.ISOLATION_READ_UNCOMMITTED:** 最低的隔离级别,允许读取尚未提交的数据变更,**可能会导致脏读、幻读或不可重复读**
+- **TransactionDefinition.ISOLATION_READ_COMMITTED:** 允许读取并发事务已经提交的数据,**可以阻止脏读,但是幻读或不可重复读仍有可能发生**
+- **TransactionDefinition.ISOLATION_REPEATABLE_READ:** 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,**可以阻止脏读和不可重复读,但幻读仍有可能发生。**
+- **TransactionDefinition.ISOLATION_SERIALIZABLE:** 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,**该级别可以防止脏读、不可重复读以及幻读**。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
+
+## Spring 事务中哪几种事务传播行为?
+
+**支持当前事务的情况:**
+
+- **TransactionDefinition.PROPAGATION_REQUIRED:** 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
+- **TransactionDefinition.PROPAGATION_SUPPORTS:** 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
+- **TransactionDefinition.PROPAGATION_MANDATORY:** 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
+
+**不支持当前事务的情况:**
+
+- **TransactionDefinition.PROPAGATION_REQUIRES_NEW:** 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
+- **TransactionDefinition.PROPAGATION_NOT_SUPPORTED:** 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
+- **TransactionDefinition.PROPAGATION_NEVER:** 以非事务方式运行,如果当前存在事务,则抛出异常。
+
+**其他情况:**
+
+- **TransactionDefinition.PROPAGATION_NESTED:** 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
+
+## 参考
+
+- 《Spring 技术内幕》
+-
+-
+-
+-
+-
+-
+
+### 公众号
+
+如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
+
+**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取!
+
+**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
+
+
\ No newline at end of file
From 94021ede47a2ebae0983f9fcf5d76365e1b70619 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 30 May 2019 12:33:58 +0800
Subject: [PATCH 02/25] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index c5bfd282454..70b509929fe 100644
--- a/README.md
+++ b/README.md
@@ -168,6 +168,7 @@
#### Spring
- [Spring 学习与面试](docs/system-design/framework/spring/Spring.md)
+- [Spring 常见问题总结](docs/system-design/framework/spring/SpringInterviewQuestions.md)
- [Spring中bean的作用域与生命周期](docs/system-design/framework/spring/SpringBean.md)
- [SpringMVC 工作原理详解](docs/system-design/framework/spring/SpringMVC-Principle.md)
- [Spring中都用到了那些设计模式?](docs/system-design/framework/spring/Spring-Design-Patterns.md)
From 569d73d5bbbd8981c49e703718af0a74cfdd05ff Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 30 May 2019 13:44:13 +0800
Subject: [PATCH 03/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BE=E7=89=87?=
=?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...267\245\345\205\267\346\200\273\347\273\223.md" | 9 +++++----
...236\203\345\234\276\345\233\236\346\224\266.md" | 10 +++-------
...261\273\345\212\240\350\275\275\345\231\250.md" | 4 ++--
...212\240\350\275\275\350\277\207\347\250\213.md" | 6 +++---
...226\207\344\273\266\347\273\223\346\236\204.md" | 14 +++++++-------
...256\227\346\234\272\347\275\221\347\273\234.md" | 2 +-
.../framework/spring/Spring-Design-Patterns.md | 8 ++++----
7 files changed, 25 insertions(+), 28 deletions(-)
diff --git "a/docs/java/jvm/JDK\347\233\221\346\216\247\345\222\214\346\225\205\351\232\234\345\244\204\347\220\206\345\267\245\345\205\267\346\200\273\347\273\223.md" "b/docs/java/jvm/JDK\347\233\221\346\216\247\345\222\214\346\225\205\351\232\234\345\244\204\347\220\206\345\267\245\345\205\267\346\200\273\347\273\223.md"
index 86b482475c7..b0bf10fb5d9 100644
--- "a/docs/java/jvm/JDK\347\233\221\346\216\247\345\222\214\346\225\205\351\232\234\345\244\204\347\220\206\345\267\245\345\205\267\346\200\273\347\273\223.md"
+++ "b/docs/java/jvm/JDK\347\233\221\346\216\247\345\222\214\346\225\205\351\232\234\345\244\204\347\220\206\345\267\245\345\205\267\346\200\273\347\273\223.md"
@@ -262,7 +262,7 @@ JConsole 是基于 JMX 的可视化监视、管理工具。可以很方便的监
#### 连接 Jconsole
-
+
如果需要使用 JConsole 连接远程进程,可以在远程 Java 程序启动时加上下面这些参数:
@@ -281,7 +281,7 @@ JConsole 是基于 JMX 的可视化监视、管理工具。可以很方便的监
#### 查看 Java 程序概况
-
+
#### 内存监控
@@ -292,7 +292,7 @@ JConsole 可以显示当前内存的详细信息。不仅包括堆内存/非堆
> - **新生代 GC(Minor GC)**:指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
> - **老年代 GC(Major GC/Full GC)**:指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。
-
+
#### 线程监控
@@ -300,7 +300,7 @@ JConsole 可以显示当前内存的详细信息。不仅包括堆内存/非堆
最下面有一个"检测死锁 (D)"按钮,点击这个按钮可以自动为你找到发生死锁的线程以及它们的详细信息 。
-
+
### Visual VM:多合一故障处理工具
@@ -324,6 +324,7 @@ VisualVM 提供在 Java 虚拟机 (Java Virutal Machine, JVM) 上运行的 Java
-
-
+## 公众号
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
diff --git "a/docs/java/jvm/JVM\345\236\203\345\234\276\345\233\236\346\224\266.md" "b/docs/java/jvm/JVM\345\236\203\345\234\276\345\233\236\346\224\266.md"
index 30e26032bc6..b73c5412667 100644
--- "a/docs/java/jvm/JVM\345\236\203\345\234\276\345\233\236\346\224\266.md"
+++ "b/docs/java/jvm/JVM\345\236\203\345\234\276\345\233\236\346\224\266.md"
@@ -72,7 +72,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(G
上图所示的 eden 区、s0("From") 区、s1("To") 区都属于新生代,tentired 区属于老年代。大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s1("To"),并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。经过这次GC后,Eden区和"From"区已经被清空。这个时候,"From"和"To"会交换他们的角色,也就是新的"To"就是上次GC前的“From”,新的"From"就是上次GC前的"To"。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,"To"区被填满之后,会将所有对象移动到年老代中。
-
+
### 1.1 对象优先在 eden 区分配
@@ -193,8 +193,6 @@ JDK1.2 之前,Java 中引用的定义很传统:如果 reference 类型的数
JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用四种(引用强度逐渐减弱)
-
-
**1.强引用**
以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果一个对象具有强引用,那就类似于**必不可少的生活用品**,垃圾回收器绝不会回收它。当内存空 间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
@@ -250,7 +248,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
## 3 垃圾收集算法
-
+
### 3.1 标记-清除算法
@@ -284,7 +282,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
## 4 垃圾收集器
-
+
**如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。**
@@ -301,8 +299,6 @@ Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收
但是 Serial 收集器有没有优于其他垃圾收集器的地方呢?当然有,它**简单而高效(与其他收集器的单线程相比)**。Serial 收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。Serial 收集器对于运行在 Client 模式下的虚拟机来说是个不错的选择。
-
-
### 4.2 ParNew 收集器
**ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。**
diff --git "a/docs/java/jvm/\347\261\273\345\212\240\350\275\275\345\231\250.md" "b/docs/java/jvm/\347\261\273\345\212\240\350\275\275\345\231\250.md"
index a410824321d..fa93f93adfa 100644
--- "a/docs/java/jvm/\347\261\273\345\212\240\350\275\275\345\231\250.md"
+++ "b/docs/java/jvm/\347\261\273\345\212\240\350\275\275\345\231\250.md"
@@ -18,7 +18,7 @@
类加载过程:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。
-
+
一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 `loadClass()` 方法)。数组类型不通过类加载器创建,它由 Java 虚拟机直接创建。
@@ -38,7 +38,7 @@ JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其他
每一个类都有一个对应它的类加载器。系统中的 ClassLoder 在协同工作的时候会默认使用 **双亲委派模型** 。即在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。**加载的时候,首先会把该请求委派该父类加载器的 `loadClass()` 处理,因此所有的请求最终都应该传送到顶层的启动类加载器 `BootstrapClassLoader` 中。当父类加载器无法处理时,才由自己来处理。**当父类加载器为null时,会使用启动类加载器 `BootstrapClassLoader` 作为父类加载器。
-
+
每个类加载都有一个父类加载器,我们通过下面的程序来验证。
diff --git "a/docs/java/jvm/\347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md" "b/docs/java/jvm/\347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md"
index bbe86e7d37f..e08c5040a1b 100644
--- "a/docs/java/jvm/\347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md"
+++ "b/docs/java/jvm/\347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md"
@@ -17,7 +17,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚
系统加载 Class 类型的文件主要三步:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。
-
+
## 加载
@@ -37,7 +37,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚
## 验证
-
+
## 准备
@@ -48,7 +48,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚
**基本数据类型的零值:**
-
+
## 解析
diff --git "a/docs/java/jvm/\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md" "b/docs/java/jvm/\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md"
index 499c16bae15..2e427deb55c 100644
--- "a/docs/java/jvm/\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md"
+++ "b/docs/java/jvm/\347\261\273\346\226\207\344\273\266\347\273\223\346\236\204.md"
@@ -58,7 +58,7 @@ ClassFile {
**Class文件字节码结构组织示意图** (之前在网上保存的,非常不错,原出处不明):
-
+
### 2.1 魔数
@@ -123,7 +123,7 @@ ClassFile {
类访问和属性修饰符:
-
+
我们定义了一个 Employee 类
@@ -136,7 +136,7 @@ public class Employee {
通过`javap -v class类名` 指令来看一下类的访问标志。
-
+
### 2.5 当前类索引,父类索引与接口索引集合
@@ -162,7 +162,7 @@ public class Employee {
**field info(字段表) 的结构:**
-
+
- **access_flags:** 字段的作用域(`public` ,`private`,`protected`修饰符),是实例变量还是类变量(`static`修饰符),可否被序列化(transient 修饰符),可变性(final),可见性(volatile 修饰符,是否强制从主内存读写)。
- **name_index:** 对常量池的引用,表示的字段的名称;
@@ -174,7 +174,7 @@ public class Employee {
**字段的 access_flags 的取值:**
-
+
### 2.7 方法表集合
@@ -189,11 +189,11 @@ Class 文件存储格式中对方法的描述与对字段的描述几乎采用
**method_info(方法表的) 结构:**
-
+
**方法表的 access_flag 取值:**
-
+
注意:因为`volatile`修饰符和`transient`修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了`synchronized`、`native`、`abstract`等关键字修饰方法,所以也就多了这些关键字对应的标志。
diff --git "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" "b/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
index 2d076d62b1d..c4c87d5315a 100644
--- "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
+++ "b/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
@@ -291,7 +291,7 @@ HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说
最常用的就是利用 URL 重写把 Session ID 直接附加在URL路径的后面。
-
+
## 十 Cookie的作用是什么?和Session有什么区别?
diff --git a/docs/system-design/framework/spring/Spring-Design-Patterns.md b/docs/system-design/framework/spring/Spring-Design-Patterns.md
index 2bab4237f14..51ab91e8406 100644
--- a/docs/system-design/framework/spring/Spring-Design-Patterns.md
+++ b/docs/system-design/framework/spring/Spring-Design-Patterns.md
@@ -30,7 +30,7 @@ Design Patterns(设计模式) 表示面向对象软件开发中最好的计算
**IoC(Inversion of Control,控制翻转)** 是Spring 中一个非常非常重要的概念,它不是什么技术,而是一种解耦的设计思想。它的主要目的是借助于“第三方”(Spring 中的 IOC 容器) 实现具有依赖关系的对象之间的解耦(IOC容易管理对象,你只管使用即可),从而降低代码之间的耦合度。**IOC 是一个原则,而不是一个模式,以下模式(但不限于)实现了IoC原则。**
-
+
**Spring IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。** IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。
@@ -134,7 +134,7 @@ AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无
**Spring AOP 就是基于动态代理的**,如果要代理的对象,实现了某个接口,那么Spring AOP会使用**JDK Proxy**,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用**Cglib** ,这时候Spring AOP会使用 **Cglib** 生成一个被代理对象的子类来作为代理,如下图所示:
-
+
当然你也可以使用 AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。
@@ -206,7 +206,7 @@ Spring 中默认存在以下事件,他们都是对 `ApplicationContextEvent`
- `ContextRefreshedEvent`:`ApplicationContext` 初始化或刷新完成后触发的事件;
- `ContextClosedEvent`:`ApplicationContext` 关闭后触发的事件。
-
+
#### 事件监听者角色
@@ -323,7 +323,7 @@ if(mappedHandler.getHandler() instanceof MultiActionController){
装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。其实在 JDK 中就有很多地方用到了装饰者模式,比如 `InputStream`家族,`InputStream` 类下有 `FileInputStream` (读取文件)、`BufferedInputStream` (增加缓存,使读取文件速度大大提升)等子类都在不修改`InputStream` 代码的情况下扩展了它的功能。
-
+
Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源。我们能否根据客户的需求在少修改原有类的代码下动态切换不同的数据源?这个时候就要用到装饰者模式(这一点我自己还没太理解具体原理)。Spring 中用到的包装器模式在类名上含有 `Wrapper`或者 `Decorator`。这些类基本上都是动态地给一个对象添加一些额外的职责
From 6a3c5b94a69098b9b2d9c68372cb581c7fc0af63 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 30 May 2019 13:59:46 +0800
Subject: [PATCH 04/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BE=E7=89=87?=
=?UTF-8?q?=E9=93=BE=E6=8E=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...72\347\241\200\347\237\245\350\257\206.md" | 12 +++++++-
...cyBasicsCommonInterviewQuestionsSummary.md | 4 ++-
...01\351\235\242\350\257\225\351\242\230.md" | 29 ++++++++++++++-----
3 files changed, 36 insertions(+), 9 deletions(-)
diff --git "a/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md"
index 3bb362d36e3..9090dcb97e7 100644
--- "a/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md"
+++ "b/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md"
@@ -300,4 +300,14 @@ Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但
Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。
-Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
\ No newline at end of file
+Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
+
+## 公众号
+
+如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
+
+**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取!
+
+**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
+
+
\ No newline at end of file
diff --git a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
index 3dd8f9ba145..4b55a36e4fb 100644
--- a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
+++ b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
@@ -77,7 +77,9 @@ public class MultiThread {
下图是 Java 内存区域,通过下图我们从 JVM 的角度来说一下线程和进程之间的关系。如果你对 Java 内存区域 (运行时数据区) 这部分知识不太了解的话可以阅读一下这篇文章:[《可能是把 Java 内存区域讲的最清楚的一篇文章》]()
-
+
+

+
从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的**堆**和**方法区 (JDK1.8 之后的元空间)**资源,但是每个线程有自己的**程序计数器**、**虚拟机栈** 和 **本地方法栈**。
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
index b45892f545d..11f8d323b9a 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
@@ -3,7 +3,7 @@
- [剖析面试最常见问题之Java基础知识](#剖析面试最常见问题之java基础知识)
- [说说List,Set,Map三者的区别?](#说说listsetmap三者的区别)
- [Arraylist 与 LinkedList 区别?](#arraylist-与-linkedlist-区别)
- - [**补充内容:RandomAccess接口**](#补充内容randomaccess接口)
+ - [补充内容:RandomAccess接口](#补充内容randomaccess接口)
- [补充内容:双向链表和双向循环链表](#补充内容双向链表和双向循环链表)
- [ArrayList 与 Vector 区别呢?为什么要用Arraylist取代Vector呢?](#arraylist-与-vector-区别呢为什么要用arraylist取代vector呢)
- [说一说 ArrayList 的扩容机制吧](#说一说-arraylist-的扩容机制吧)
@@ -28,7 +28,6 @@
- [2. Set](#2-set)
- [Map](#map)
- [如何选用集合?](#如何选用集合)
- - [集合的选用](#集合的选用)
@@ -88,7 +87,7 @@ ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什
**双向循环链表:** 最后一个节点的 next 指向head,而 head 的prev指向最后一个节点,构成一个环。
-
+
## ArrayList 与 Vector 区别呢?为什么要用Arraylist取代Vector呢?
@@ -252,9 +251,17 @@ ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方
图片来源:
-HashTable: [](https://camo.githubusercontent.com/b8e66016373bb109e923205857aeee9689baac9e/687474703a2f2f6d792d626c6f672d746f2d7573652e6f73732d636e2d6265696a696e672e616c6979756e63732e636f6d2f31382d382d32322f35303635363638312e6a7067)
+**HashTable:**
-**JDK1.7的ConcurrentHashMap:** [](https://camo.githubusercontent.com/443af05b6be6ed09e50c78a1dca39bf75acb106d/687474703a2f2f6d792d626c6f672d746f2d7573652e6f73732d636e2d6265696a696e672e616c6979756e63732e636f6d2f31382d382d32322f33333132303438382e6a7067)**JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点):** [](https://camo.githubusercontent.com/2d779bf515db75b5bf364c4f23c31268330a865e/687474703a2f2f6d792d626c6f672d746f2d7573652e6f73732d636e2d6265696a696e672e616c6979756e63732e636f6d2f31382d382d32322f39373733393232302e6a7067)
+
+
+**JDK1.7的ConcurrentHashMap:**
+
+
+
+**JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点):**
+
+
## ConcurrentHashMap线程安全的具体实现方式/底层具体实现
@@ -434,6 +441,14 @@ Output:
## 如何选用集合?
-## 集合的选用
-
主要根据集合的特点来选用,比如我们需要根据键值获取到元素值时就选用Map接口下的集合,需要排序时选择TreeMap,不需要排序时就选择HashMap,需要保证线程安全就选用ConcurrentHashMap.当我们只需要存放元素值时,就选择实现Collection接口的集合,需要保证元素唯一时选择实现Set接口的集合比如TreeSet或HashSet,不需要就选择实现List接口的比如ArrayList或LinkedList,然后再根据实现这些接口的集合的特点来选用。
+
+## 公众号
+
+如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
+
+**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取!
+
+**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
+
+
\ No newline at end of file
From 8a173a00e2cb9d3932a1e2ee8cf130c3016fa399 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 30 May 2019 14:10:03 +0800
Subject: [PATCH 05/25] Update README.md
---
README.md | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 70b509929fe..c7123c8ba1c 100644
--- a/README.md
+++ b/README.md
@@ -18,15 +18,13 @@
-
+
-
+
-
-
推荐使用 在线阅读(访问速度慢的话,请使用 ),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
## 目录
From 149c64b9e689fe4ecbba997b62d988104d3b260a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E6=96=87=E5=B9=BF?=
Date: Fri, 31 May 2019 01:25:17 +0800
Subject: [PATCH 06/25] =?UTF-8?q?[RocketMQ-Questions.md]=20=E8=A1=A5?=
=?UTF-8?q?=E5=85=85=E9=A1=BA=E5=BA=8F=E6=B6=88=E8=B4=B9=E4=BB=A5=E5=8F=8A?=
=?UTF-8?q?=20Broker=20=E7=9A=84=20Raft=20=E9=80=89=E4=B8=BE=E7=89=B9?=
=?UTF-8?q?=E6=80=A7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../data-communication/RocketMQ-Questions.md | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/docs/system-design/data-communication/RocketMQ-Questions.md b/docs/system-design/data-communication/RocketMQ-Questions.md
index 81b701aca87..a41a4035b7b 100644
--- a/docs/system-design/data-communication/RocketMQ-Questions.md
+++ b/docs/system-design/data-communication/RocketMQ-Questions.md
@@ -155,7 +155,10 @@ class Broker {
### 2.1.5 顺序消息的实现
-与定时消息同原理,生产者生产消息时指定特定的 MessageQueue ,消费者消费消息时,消费特定的 MessageQueue,其实单机版的消息中心在一个 MessageQueue 就天然支持了顺序消息
+1. 与定时消息同原理,生产者生产消息时指定特定的 MessageQueue ,消费者消费消息时,消费特定的 MessageQueue,其实单机版的消息中心在一个 MessageQueue 就天然支持了顺序消息
+2. 注意:同一个 MessageQueue 保证里面的消息是顺序消费的前提是:消费者是串行的消费该 MessageQueue,因为就算 MessageQueue 是顺序的,但是当并行消费时,还是会有顺序问题,但是串行消费也同时引入了两个问题:
+>1. 引入锁来实现串行
+>2. 前一个消费阻塞时后面都会被阻塞
### 2.1.6 分布式消息的实现
@@ -194,8 +197,9 @@ class Broker {
加分项咯
1. 包括组件通信间使用 Netty 的自定义协议
2. 消息重试负载均衡策略(具体参考 Dubbo 负载均衡策略)
-3. 消息过滤器(Producer 发送消息到 Broker,Broker 存储消息信息,Consumer 消费时请求 Broker 端从磁盘文件查询消息文件时就使用过滤服务器进行过滤)
+3. 消息过滤器(Producer 发送消息到 Broker,Broker 存储消息信息,Consumer 消费时请求 Broker 端从磁盘文件查询消息文件时,在 Broker 端就使用过滤服务器进行过滤)
4. Broker 同步双写和异步双写中 Master 和 Slave 的交互
+5. Broker 在 4.5.0 版本更新中引入了基于 Raft 协议的多副本选举,之前这是商业版才有的特性 [ISSUE-1046][2]
# 3 参考
@@ -207,3 +211,4 @@ class Broker {
6. 基于《RocketMQ技术内幕》源码注释:https://github.com/LiWenGu/awesome-rocketmq
[1]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/RocketMQ%E6%B5%81%E7%A8%8B.png
+[2]: http://rocketmq.apache.org/release_notes/release-notes-4.5.0/
From 58bb96f3cebea38d6b76472b92be20ce9cc1fea9 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Sat, 1 Jun 2019 18:31:26 +0800
Subject: [PATCH 07/25] Update
JavaConcurrencyAdvancedCommonInterviewQuestions.md
---
.../JavaConcurrencyAdvancedCommonInterviewQuestions.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
index b291dc0aa1a..b994e722303 100644
--- a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
+++ b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
@@ -55,7 +55,7 @@ synchronized关键字解决的是多个线程之间访问资源的同步性,sy
- **修饰静态方法:** :也就是给当前类加锁,会作用于类的所有对象实例,因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管new了多少个对象,只有一份)。所以如果一个线程A调用一个实例对象的非静态 synchronized 方法,而线程B需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,**因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁**。
- **修饰代码块:** 指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
-**总结:** synchronized 关键字加到 static 静态方法和 synchronized(class)代码块上都是是给 Class 类上锁。synchronized 关键字加到静态方法上是给对象实例上锁。尽量不要使用 synchronized(String a) 因为JVM中,字符串常量池具有缓存功能!
+**总结:** synchronized 关键字加到 static 静态方法和 synchronized(class)代码块上都是是给 Class 类上锁。synchronized 关键字加到实例方法上是给对象实例上锁。尽量不要使用 synchronized(String a) 因为JVM中,字符串常量池具有缓存功能!
下面我以一个常见的面试题为例讲解一下 synchronized 关键字的具体使用。
From 52fb6792b951624d2d4bf247481ab9fbdca151c8 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Sat, 1 Jun 2019 18:39:44 +0800
Subject: [PATCH 08/25] =?UTF-8?q?Update=20=E5=87=A0=E9=81=93=E5=B8=B8?=
=?UTF-8?q?=E8=A7=81=E7=9A=84=E9=93=BE=E8=A1=A8=E7=AE=97=E6=B3=95=E9=A2=98?=
=?UTF-8?q?.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git "a/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" "b/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md"
index 79b74441deb..85e2934e407 100644
--- "a/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md"
+++ "b/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md"
@@ -225,7 +225,7 @@ public class Solution {
while (node1 != null) {
node1 = node1.next;
count++;
- if (k < 1 && node1 != null) {
+ if (k < 1) {
node2 = node2.next;
}
k--;
From de1beb701f51f2520de655d19f34558e9cbfa4d2 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Wed, 5 Jun 2019 09:30:33 +0800
Subject: [PATCH 09/25] =?UTF-8?q?Update=20Java=E9=9B=86=E5=90=88=E6=A1=86?=
=?UTF-8?q?=E6=9E=B6=E5=B8=B8=E8=A7=81=E9=9D=A2=E8=AF=95=E9=A2=98.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...\270\350\247\201\351\235\242\350\257\225\351\242\230.md" | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
index 11f8d323b9a..ffa50ff98fe 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
@@ -83,11 +83,11 @@ ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什
**双向链表:** 包含两个指针,一个prev指向前一个节点,一个next指向后一个节点。
-
+
**双向循环链表:** 最后一个节点的 next 指向head,而 head 的prev指向最后一个节点,构成一个环。
-
+
## ArrayList 与 Vector 区别呢?为什么要用Arraylist取代Vector呢?
@@ -451,4 +451,4 @@ Output:
**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
\ No newline at end of file
+
From 3089b0aff76a964f08f917df9dd70e0c3541a4f0 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Wed, 5 Jun 2019 14:12:01 +0800
Subject: [PATCH 10/25] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?=
=?UTF-8?q?=E7=BD=91=E7=BB=9C.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" "b/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
index c4c87d5315a..26816f5aeeb 100644
--- "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
+++ "b/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
@@ -228,10 +228,10 @@ TCP的拥塞控制采用了四种算法,即 **慢开始** 、 **拥塞避免**
- **拥塞避免:** 拥塞避免算法的思路是让拥塞窗口cwnd缓慢增大,即每经过一个往返时间RTT就把发送放的cwnd加1.
- **快重传与快恢复:**
在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
+

-
## 五 在浏览器中输入url地址 ->> 显示主页的过程(面试常客)
百度好像最喜欢问这个问题。
> 打开一个网页,整个过程会使用哪些协议
From afe39e758229a79384c0b03f8d5bd3841921e08e Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Fri, 7 Jun 2019 20:48:09 +0800
Subject: [PATCH 11/25] Create 2019-5.md
---
docs/github-trending/2019-5.md | 125 +++++++++++++++++++++++++++++++++
1 file changed, 125 insertions(+)
create mode 100644 docs/github-trending/2019-5.md
diff --git a/docs/github-trending/2019-5.md b/docs/github-trending/2019-5.md
new file mode 100644
index 00000000000..1ac28b22cd7
--- /dev/null
+++ b/docs/github-trending/2019-5.md
@@ -0,0 +1,125 @@
+以下涉及到的数据统计与 2019 年 6 月 1 日 18 点,数据来源: 。下面推荐的内容从 Java 学习文档到最热门的框架再到热门的工具应有尽有,建议收藏+在看!
+
+### 1.LeetCodeAnimation
+
+- **Github 地址**:
+- **Star**: 29.0k (11,492 stars this month)
+- **介绍**: Demonstrate all the questions on LeetCode in the form of animation.(用动画的形式呈现解LeetCode题目的思路)。
+
+### 2.CS-Notes
+
+- **Github 地址**:
+- **Star**: 64.4k (5513 stars this month)
+- **介绍**: 技术面试必备基础知识、Leetcode 题解、后端面试、Java 面试、春招、秋招、操作系统、计算机网络、系统设计。
+
+### 3.JavaGuide
+
+- **Github 地址**:
+- **Star**: 42.0k (4,442 stars this month)
+- **介绍**: 【Java 学习+面试指南】 一份涵盖大部分 Java 程序员所需要掌握的核心知识。
+
+### 4.mall
+
+- **Github 地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall)
+- **star**: 14.6 k (3,086 stars this month)
+- **介绍**: mall 项目是一套电商系统,包括前台商城系统及后台管理系统,基于 SpringBoot+MyBatis 实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。
+
+### 5.advanced-java
+
+- **Github 地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java)
+- **Star**: 20.8k (2,394 stars this month)
+- **介绍**: 互联网 Java 工程师进阶知识完全扫盲。
+
+### 6.spring-boot
+
+- **Github地址**: [https://github.com/spring-projects/spring-boot](https://github.com/spring-projects/spring-boot)
+- **star:** 38.5k (1,339 stars this month)
+- **介绍**: 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。 另外Spring Cloud也是基于Spring Boot构建的,我个人非常有必要学习一下。
+
+**Spring Boot官方的介绍:**
+
+> Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可)
+
+### 7. Java
+
+- **Github 地址**:
+- **Star**:14.3k (1,334 stars this month)
+- **介绍**: All Algorithms implemented in Java。
+
+### 8.server
+
+- **Github 地址**:
+- **star**: 2.2 k (1,275 stars this month)
+- **介绍**: 全开源即时通讯(IM)系统。
+
+### 9.litemall
+
+- **Github 地址**:
+- **Star**: 7.1k (1,114 stars this month)
+- **介绍**: 又一个小商城。litemall = Spring Boot后端 + Vue管理员前端 + 微信小程序用户前端 + Vue用户移动端。
+
+### 10.Linkage-RecyclerView
+
+- **Github 地址**:
+- **Star**: 10.0k (1,093 stars this month)
+- **介绍**: 即使不用饿了么订餐,也请务必收藏好该库!🔥 一行代码即可接入,二级联动订餐列表 - Even if you don't order food by PrubHub, be sure to collect this library, please! 🔥 This secondary linkage list widget can be accessed by only one line of code. Supporting by RecyclerView & AndroidX.
+
+### 11.toBeTopJavaer
+
+- **Github 地址** :
+- **Star**: 3.3k (1,007 stars this month)
+- **介绍**: To Be Top Javaer - Java工程师成神之路
+
+### 12.elasticsearch
+
+- **Github 地址** : [https://github.com/elastic/elasticsearch](https://github.com/elastic/elasticsearch)
+- **Star**: 48.0k (968 stars this month)
+- **介绍**: Design patterns implemented in Java。
+
+### 13.java-design-patterns
+
+- **Github 地址** :
+- **Star**: 41.5k (955 stars this month)
+- **介绍**: 开源,分布式,RESTful 搜索引擎。
+
+### 14.apollo
+
+- **Github 地址** :
+- **Star**: 14.5k (927 stars this month)
+- **介绍**: Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
+
+### 15.arthas
+
+- **Github地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas)
+- **star**: 13.5 k (933 stars this month)
+- **介绍**: Arthas 是Alibaba开源的Java诊断工具。
+
+### 16.dubbo
+
+- **Github地址**:
+- **star**: 26.9 k (769 stars this month)
+- **介绍**: Apache Dubbo是一个基于Java的高性能开源RPC框架。
+
+### 17.DoraemonKit
+
+- **Github地址**:
+- **Star**: 8.5k (909 stars this month)
+- **介绍**: 简称 "DoKit" 。一款功能齐全的客户端( iOS 、Android )研发助手,你值得拥有。
+
+### 18.halo
+
+- **Github地址**:
+- **Star**: 4.1k (829 stars this month)
+- **介绍**: Halo 可能是最好的 Java 博客系统。
+
+### 19.seata
+
+- **Github 地址** : [https://github.com/seata/seata](https://github.com/seata/seata)
+- **star**: 9.2 k (776 stars this month)
+- **介绍**: Seata 是一种易于使用,高性能,基于 Java 的开源分布式事务解决方案。
+
+### 20.hutool
+
+- **Github地址**:
+- **star**: 5,3 k (812 stars this month)
+- **介绍**: Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。Hutool最初是我项目中“util”包的一个整理,后来慢慢积累并加入更多非业务相关功能,并广泛学习其它开源项目精髓,经过自己整理修改,最终形成丰富的开源工具集。官网: 。
\ No newline at end of file
From a00c739c38aa436210ca78225b8ca60815d766af Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Tue, 11 Jun 2019 22:36:29 +0800
Subject: [PATCH 12/25] =?UTF-8?q?Update=20=E4=BA=8B=E5=8A=A1=E9=9A=94?=
=?UTF-8?q?=E7=A6=BB=E7=BA=A7=E5=88=AB(=E5=9B=BE=E6=96=87=E8=AF=A6?=
=?UTF-8?q?=E8=A7=A3).md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...253(\345\233\276\346\226\207\350\257\246\350\247\243).md" | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git "a/docs/database/\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253(\345\233\276\346\226\207\350\257\246\350\247\243).md" "b/docs/database/\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253(\345\233\276\346\226\207\350\257\246\350\247\243).md"
index 4cd950d5357..1e6f5816b74 100644
--- "a/docs/database/\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253(\345\233\276\346\226\207\350\257\246\350\247\243).md"
+++ "b/docs/database/\344\272\213\345\212\241\351\232\224\347\246\273\347\272\247\345\210\253(\345\233\276\346\226\207\350\257\246\350\247\243).md"
@@ -26,9 +26,8 @@
### 事物的特性(ACID)
-
-

-
+
+
1. **原子性:** 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
2. **一致性:** 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
From 732950e8fad3f00ee9ef91c23902e80350299234 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Tue, 11 Jun 2019 23:11:07 +0800
Subject: [PATCH 13/25] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c7123c8ba1c..12ea60d3efa 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
-推荐使用 在线阅读(访问速度慢的话,请使用 ),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
+推荐使用 https://snailclimb.top/JavaGuide/ 在线阅读(访问速度慢的话,请使用 https://snailclimb.gitee.io/javaguide),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
## 目录
From f771f27163414ef0debc4d030745aaee4831c837 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Tue, 11 Jun 2019 23:11:39 +0800
Subject: [PATCH 14/25] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 12ea60d3efa..e13416b96c4 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
-推荐使用 https://snailclimb.top/JavaGuide/ 在线阅读(访问速度慢的话,请使用 https://snailclimb.gitee.io/javaguide),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
+推荐使用 https://snailclimb.top/JavaGuide/ 在线阅读(访问速度慢的话,请使用 https://snailclimb.gitee.io/javaguide ),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
## 目录
From 1d8787ae0f6e375a08a5ec90aed31d4de7c5cbef Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Wed, 12 Jun 2019 08:37:30 +0800
Subject: [PATCH 15/25] =?UTF-8?q?Update=20Java=E5=9F=BA=E7=A1=80=E7=9F=A5?=
=?UTF-8?q?=E8=AF=86.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Java\345\237\272\347\241\200\347\237\245\350\257\206.md" | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git "a/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
index 2e7e0fe357e..b8f1e6bfdb0 100644
--- "a/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
+++ "b/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
@@ -489,10 +489,10 @@ Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很
按操作方式分类结构图:
-
+
-按操作对象分类结构图
+按操作对象分类结构图:

From 8af50f39a41cb73d2549a91b009ca11598991164 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Thu, 13 Jun 2019 09:24:38 +0800
Subject: [PATCH 16/25] Update
JavaConcurrencyAdvancedCommonInterviewQuestions.md
---
.../JavaConcurrencyAdvancedCommonInterviewQuestions.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
index b994e722303..ba1869d0b98 100644
--- a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
+++ b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
@@ -204,7 +204,7 @@ synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团
再举个简单的例子:
-比如有两个人去宝屋收集宝物,这两个共用一个袋子的话肯定会产生争执,但是给他们两个人每个人分配一个袋子的话就不会出现这样的问题。如果把这两个人比作线程的话,那么ThreadLocal就是用来这两个线程竞争的。
+比如有两个人去宝屋收集宝物,这两个共用一个袋子的话肯定会产生争执,但是给他们两个人每个人分配一个袋子的话就不会出现这样的问题。如果把这两个人比作线程的话,那么ThreadLocal就是用来避免这两个线程竞争的。
### 3.2. ThreadLocal示例
From 915d4a200badf3bc0253ee1f9af6ae62003818c3 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Sat, 15 Jun 2019 23:06:01 +0800
Subject: [PATCH 17/25] =?UTF-8?q?Update=20Java=E5=9F=BA=E7=A1=80=E7=9F=A5?=
=?UTF-8?q?=E8=AF=86.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...72\347\241\200\347\237\245\350\257\206.md" | 43 +++++++------------
1 file changed, 16 insertions(+), 27 deletions(-)
diff --git "a/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
index b8f1e6bfdb0..7e79094e283 100644
--- "a/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
+++ "b/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
@@ -59,17 +59,8 @@
## 1. 面向对象和面向过程的区别
-### 面向过程
-
-**优点:** 性能比面向对象高。因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发
-
-**缺点:** 没有面向对象易维护、易复用、易扩展
-
-### 面向对象
-
-**优点:** 易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
-
-**缺点:** 性能比面向过程低
+- **面向过程** :**面向过程性能比面向对象高。** 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发。但是,**面向过程没有面向对象易维护、易复用、易扩展。**
+- **面向对象** :**面向对象易维护、易复用、易扩展。** 因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,**面向过程性能比面向过程低**。
## 2. Java 语言有哪些特点?
@@ -100,7 +91,9 @@ Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同
> HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是JIT所需要编译的部分。JVM会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9引入了一种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销。JDK支持分层编译和AOT协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。
-总结:Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
+**总结:**
+
+Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
### JDK 和 JRE
@@ -120,7 +113,7 @@ JRE 是 Java运行时环境。它是运行已编译 Java 程序所需的所有
>
> 答:非常接近 - 我们的Oracle JDK版本构建过程基于OpenJDK 7构建,只添加了几个部分,例如部署代码,其中包括Oracle的Java插件和Java WebStart的实现,以及一些封闭的源代码派对组件,如图形光栅化器,一些开源的第三方组件,如Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源Oracle JDK的所有部分,除了我们考虑商业功能的部分。
-总结:
+**总结:**
1. Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
2. OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;
@@ -145,7 +138,7 @@ JRE 是 Java运行时环境。它是运行已编译 Java 程序所需的所有
## 7. Java 应用程序与小程序之间有那些差别?
-简单说应用程序是从主线程启动(也就是 main() 方法)。applet 小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟 flash 的小游戏类似。
+简单说应用程序是从主线程启动(也就是 `main()` 方法)。applet 小程序没有 `main()` 方法,主要是嵌在浏览器页面上运行(调用`init()`或者`run()`来启动),嵌入浏览器这点跟 flash 的小游戏类似。
## 8. 字符型常量和字符串常量的区别?
@@ -162,9 +155,8 @@ JRE 是 Java运行时环境。它是运行已编译 Java 程序所需的所有
## 10. 重载和重写的区别
-**重载:** 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
-
-**重写:** 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
+- **重载:** 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
+- **重写:** 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
## 11. Java 面向对象编程三大特性: 封装 继承 多态
@@ -191,7 +183,6 @@ JRE 是 Java运行时环境。它是运行已编译 Java 程序所需的所有
## 12. String StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?
**可变性**
-
简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,`private final char value[]`,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串`char[]value` 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
@@ -213,8 +204,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
**线程安全性**
-String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
-
+String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
**性能**
@@ -228,9 +218,8 @@ String 中的对象是不可变的,也就可以理解为常量,线程安全
## 13. 自动装箱与拆箱
-**装箱**:将基本类型用它们对应的引用类型包装起来;
-
-**拆箱**:将包装类型转换为基本数据类型;
+- **装箱**:将基本类型用它们对应的引用类型包装起来;
+- **拆箱**:将包装类型转换为基本数据类型;
## 14. 在一个静态方法内调用一个非静态成员为什么是非法的?
@@ -238,7 +227,7 @@ String 中的对象是不可变的,也就可以理解为常量,线程安全
## 15. 在 Java 中定义一个不做事且没有参数的构造方法的作用
-Java 程序在执行子类的构造方法之前,如果没有用 super() 来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
+Java 程序在执行子类的构造方法之前,如果没有用 `super() `来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 `super() `来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
## 16. import java和javax有什么区别?
@@ -489,12 +478,12 @@ Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很
按操作方式分类结构图:
-
+
按操作对象分类结构图:
-
+
### BIO,NIO,AIO 有什么区别?
@@ -524,4 +513,4 @@ Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很
**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
+
From 647990855e67108c8661b196e9330374ceeb6b0a Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Sat, 15 Jun 2019 23:20:01 +0800
Subject: [PATCH 18/25] =?UTF-8?q?Update=20J2EE=E5=9F=BA=E7=A1=80=E7=9F=A5?=
=?UTF-8?q?=E8=AF=86.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...72\347\241\200\347\237\245\350\257\206.md" | 40 +++++++++----------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git "a/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md"
index 9090dcb97e7..4d70e1c1940 100644
--- "a/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md"
+++ "b/docs/java/J2EE\345\237\272\347\241\200\347\237\245\350\257\206.md"
@@ -26,7 +26,7 @@
## Servlet总结
-在Java Web程序中,**Servlet**主要负责接收用户请求**HttpServletRequest**,在**doGet()**,**doPost()**中做相应的处理,并将回应**HttpServletResponse**反馈给用户。Servlet可以设置初始化参数,供Servlet内部使用。一个Servlet类只会有一个实例,在它初始化时调用**init()方法**,销毁时调用**destroy()方法**。**Servlet需要在web.xml中配置**(MyEclipse中创建Servlet会自动配置),**一个Servlet可以设置多个URL访问**。**Servlet不是线程安全**,因此要谨慎使用类变量。
+在Java Web程序中,**Servlet**主要负责接收用户请求 `HttpServletRequest`,在`doGet()`,`doPost()`中做相应的处理,并将回应`HttpServletResponse`反馈给用户。**Servlet** 可以设置初始化参数,供Servlet内部使用。一个Servlet类只会有一个实例,在它初始化时调用`init()`方法,销毁时调用`destroy()`方法**。**Servlet需要在web.xml中配置(MyEclipse中创建Servlet会自动配置),**一个Servlet可以设置多个URL访问**。**Servlet不是线程安全**,因此要谨慎使用类变量。
## 阐述Servlet和CGI的区别?
@@ -55,11 +55,11 @@
## Servlet接口中有哪些方法及Servlet生命周期探秘
Servlet接口定义了5个方法,其中**前三个方法与Servlet生命周期相关**:
-- **void init(ServletConfig config) throws ServletException**
-- **void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException**
-- **void destory()**
-- java.lang.String getServletInfo()
-- ServletConfig getServletConfig()
+- `void init(ServletConfig config) throws ServletException`
+- `void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException`
+- `void destory()`
+- `java.lang.String getServletInfo()`
+- `ServletConfig getServletConfig()`
**生命周期:** **Web容器加载Servlet并将其实例化后,Servlet生命周期开始**,容器运行其**init()方法**进行Servlet的初始化;请求到达时调用Servlet的**service()方法**,service()方法会根据需要调用与请求对应的**doGet或doPost**等方法;当服务器关闭或项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的**destroy()方法**。**init方法和destroy方法只会执行一次,service方法客户端每次请求Servlet都会执行**。Servlet中有时会用到一些需要初始化与销毁的资源,因此可以把初始化资源的代码放入init方法中,销毁资源的代码放入destroy方法中,这样就不需要每次处理客户端的请求都要初始化与销毁资源。
@@ -143,13 +143,11 @@ Response.setHeader("Refresh","5;URL=http://localhost:8080/servlet/example.htm");
JSP是一种Servlet,但是与HttpServlet的工作方式不太一样。HttpServlet是先由源代码编译为class文件后部署到服务器下,为先编译后部署。而JSP则是先部署后编译。JSP会在客户端第一次请求JSP文件时被编译为HttpJspPage类(接口Servlet的一个子类)。该类会被服务器临时存放在服务器工作目录里面。下面通过实例给大家介绍。
工程JspLoginDemo下有一个名为login.jsp的Jsp文件,把工程第一次部署到服务器上后访问这个Jsp文件,我们发现这个目录下多了下图这两个东东。
.class文件便是JSP对应的Servlet。编译完毕后再运行class文件来响应客户端请求。以后客户端访问login.jsp的时候,Tomcat将不再重新编译JSP文件,而是直接调用class文件来响应客户端请求。
-
+
由于JSP只会在客户端第一次请求的时候被编译 ,因此第一次请求JSP时会感觉比较慢,之后就会感觉快很多。如果把服务器保存的class文件删除,服务器也会重新编译JSP。
开发Web程序时经常需要修改JSP。Tomcat能够自动检测到JSP程序的改动。如果检测到JSP源代码发生了改动。Tomcat会在下次客户端请求JSP时重新编译JSP,而不需要重启Tomcat。这种自动检测功能是默认开启的,检测改动会消耗少量的时间,在部署Web应用的时候可以在web.xml中将它关掉。
-
-
参考:《javaweb整合开发王者归来》P97
## JSP有哪些内置对象、作用分别是什么
@@ -195,31 +193,31 @@ JSP有9个内置对象:
## request.getAttribute()和 request.getParameter()有何区别
**从获取方向来看:**
-getParameter()是获取 POST/GET 传递的参数值;
+`getParameter()`是获取 POST/GET 传递的参数值;
-getAttribute()是获取对象容器中的数据值;
+`getAttribute()`是获取对象容器中的数据值;
**从用途来看:**
-getParameter用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或url重定向传值时接收数据用。
+`getParameter()`用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或url重定向传值时接收数据用。
-getAttribute用于服务器端重定向时,即在 sevlet 中使用了 forward 函数,或 struts 中使用了
+`getAttribute()` 用于服务器端重定向时,即在 sevlet 中使用了 forward 函数,或 struts 中使用了
mapping.findForward。 getAttribute 只能收到程序用 setAttribute 传过来的值。
-另外,可以用 setAttribute,getAttribute 发送接收对象.而 getParameter 显然只能传字符串。
-setAttribute 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样getAttribute就能取得你所设下的值,当然这种方法可以传对象。session也一样,只是对象在内存中的生命周期不一样而已。getParameter只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值。
+另外,可以用 `setAttribute()`,`getAttribute()` 发送接收对象.而 `getParameter()` 显然只能传字符串。
+`setAttribute()` 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样`getAttribute()`就能取得你所设下的值,当然这种方法可以传对象。session也一样,只是对象在内存中的生命周期不一样而已。`getParameter()`只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值。
**总结:**
-getParameter 返回的是String,用于读取提交的表单中的值;(获取之后会根据实际需要转换为自己需要的相应类型,比如整型,日期类型啊等等)
+`getParameter()`返回的是String,用于读取提交的表单中的值;(获取之后会根据实际需要转换为自己需要的相应类型,比如整型,日期类型啊等等)
-getAttribute 返回的是Object,需进行转换,可用setAttribute 设置成任意对象,使用很灵活,可随时用
+`getAttribute()`返回的是Object,需进行转换,可用`setAttribute()`设置成任意对象,使用很灵活,可随时用
## include指令include的行为的区别
**include指令:** JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。 语法格式如下:
<%@ include file="文件相对 url 地址" %>
-i**nclude动作:** 动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下:
+i**nclude动作:** ``动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下:
## JSP九大内置对象,七大动作,三大指令
@@ -232,11 +230,9 @@ JSP中的四种作用域包括page、request、session和application,具体来
- **session**代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。
- **application**代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。
-
-
## 如何实现JSP或Servlet的单线程模式
对于JSP页面,可以通过page指令进行设置。
-<%@page isThreadSafe=”false”%>
+`<%@page isThreadSafe=”false”%>`
对于Servlet,可以让自定义的Servlet实现SingleThreadModel标识接口。
@@ -310,4 +306,4 @@ Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Se
**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
\ No newline at end of file
+
\ No newline at end of file
From 40cda295ce97e9d63733d70d572139f373308bbf Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Sun, 16 Jun 2019 10:40:52 +0800
Subject: [PATCH 19/25] Update README.md
---
README.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/README.md b/README.md
index e13416b96c4..6bbcf89242e 100644
--- a/README.md
+++ b/README.md
@@ -20,10 +20,6 @@
-
-
-
推荐使用 https://snailclimb.top/JavaGuide/ 在线阅读(访问速度慢的话,请使用 https://snailclimb.gitee.io/javaguide ),在线阅读内容本仓库同步一致。这种方式阅读的优势在于:有侧边栏阅读体验更好,Gitee pages 的访问速度相对来说也比较快。
From 7a7b6a4b6b431d19afdb9b7d388945b500df20f3 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Mon, 17 Jun 2019 09:21:48 +0800
Subject: [PATCH 20/25] =?UTF-8?q?Update=EF=BC=9Aoptimize=20content?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...01\351\235\242\350\257\225\351\242\230.md" | 46 +++++++++----------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
index ffa50ff98fe..57286ead27d 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
@@ -41,28 +41,28 @@
## Arraylist 与 LinkedList 区别?
-- **1. 是否保证线程安全:** ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;
+- **1. 是否保证线程安全:** `ArrayList` 和 `LinkedList` 都是不同步的,也就是不保证线程安全;
-- **2. 底层数据结构:** Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向链表数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到!)
+- **2. 底层数据结构:** `Arraylist` 底层使用的是 **`Object` 数组**;`LinkedList` 底层使用的是 **双向链表** 数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到!)
-- **3. 插入和删除是否受元素位置的影响:** ① **ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。** 比如:执行`add(E e) `方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(`add(int index, E element) `)时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② **LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。**
+- **3. 插入和删除是否受元素位置的影响:** ① **`ArrayList` 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。** 比如:执行`add(E e) `方法的时候, `ArrayList` 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(`add(int index, E element) `)时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② **`LinkedList` 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。**
-- **4. 是否支持快速随机访问:** LinkedList 不支持高效的随机元素访问,而 ArrayList 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于`get(int index) `方法)。
+- **4. 是否支持快速随机访问:** `LinkedList` 不支持高效的随机元素访问,而 `ArrayList` 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于`get(int index) `方法)。
- **5. 内存空间占用:** ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。
### **补充内容:RandomAccess接口**
-```
+```java
public interface RandomAccess {
}
```
-查看源码我们发现实际上 RandomAccess 接口中什么都没有定义。所以,在我看来 RandomAccess 接口不过是一个标识罢了。标识什么? 标识实现这个接口的类具有随机访问功能。
+查看源码我们发现实际上 `RandomAccess` 接口中什么都没有定义。所以,在我看来 `RandomAccess` 接口不过是一个标识罢了。标识什么? 标识实现这个接口的类具有随机访问功能。
-在binarySearch()方法中,它要判断传入的list 是否RamdomAccess的实例,如果是,调用indexedBinarySearch()方法,如果不是,那么调用iteratorBinarySearch()方法
+在 `binarySearch(`)方法中,它要判断传入的list 是否 `RamdomAccess` 的实例,如果是,调用`indexedBinarySearch()`方法,如果不是,那么调用`iteratorBinarySearch()`方法
-```
+```java
public static
int binarySearch(List extends Comparable super T>> list, T key) {
if (list instanceof RandomAccess || list.size() TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
@@ -273,7 +273,7 @@ ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方
Segment 实现了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色。HashEntry 用于存储键值对数据。
-```
+```java
static class Segment extends ReentrantLock implements Serializable {
}
```
@@ -424,7 +424,7 @@ Output:
- **Arraylist:** Object数组
- **Vector:** Object数组
-- **LinkedList:** 双向链表(JDK1.6之前为循环链表,JDK1.7取消了循环) 详细可阅读[JDK1.7-LinkedList循环链表优化](https://www.cnblogs.com/xingele0917/p/3696593.html)
+- **LinkedList:** 双向链表(JDK1.6之前为循环链表,JDK1.7取消了循环)
#### 2. Set
@@ -451,4 +451,4 @@ Output:
**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
+
From db8807e829f6388c5c70c54f3aa613fc2bf03a34 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Mon, 17 Jun 2019 09:22:45 +0800
Subject: [PATCH 21/25] Update:optimize content
---
docs/java/collection/ArrayList-Grow.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/docs/java/collection/ArrayList-Grow.md b/docs/java/collection/ArrayList-Grow.md
index 6dd4cc93daf..06fa5388d76 100644
--- a/docs/java/collection/ArrayList-Grow.md
+++ b/docs/java/collection/ArrayList-Grow.md
@@ -270,7 +270,6 @@ public class ArrayscopyOfTest {
10
```
-
### 3.3 两者联系和区别
**联系:**
@@ -281,8 +280,6 @@ public class ArrayscopyOfTest {
`arraycopy()` 需要目标数组,将原数组拷贝到你自己定义的数组里或者原数组,而且可以选择拷贝的起点和长度以及放入新数组中的位置 `copyOf()` 是系统自动在内部新建一个数组,并返回该数组。
-
-
## 四 `ensureCapacity`方法
ArrayList 源码中有一个 `ensureCapacity` 方法不知道大家注意到没有,这个方法 ArrayList 内部没有被调用过,所以很显然是提供给用户调用的,那么这个方法有什么作用呢?
@@ -341,7 +338,6 @@ public class EnsureCapacityTest {
```
使用ensureCapacity方法前:4637
使用ensureCapacity方法后:241
-
```
通过运行结果,我们可以很明显的看出向 ArrayList 添加大量元素之前最好先使用`ensureCapacity` 方法,以减少增量重新分配的次数
From c4b9ca76dc61e68fdbab93be9fab7176354486df Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Mon, 17 Jun 2019 09:32:28 +0800
Subject: [PATCH 22/25] Update
JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
---
...urrencyBasicsCommonInterviewQuestionsSummary.md | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
index 4b55a36e4fb..b1ee88a4e00 100644
--- a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
+++ b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
@@ -1,3 +1,5 @@
+点击关注[公众号](#公众号)免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
+
- [Java 并发基础常见面试题总结](#java-并发基础常见面试题总结)
@@ -34,7 +36,7 @@
如下图所示,在 windows 中通过查看任务管理器的方式,我们就可以清楚看到 window 当前运行的进程(.exe 文件的运行)。
-
+
### 1.2. 何为线程?
@@ -301,3 +303,13 @@ Process finished with exit code 0
new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
**总结: 调用 start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里执行。**
+
+## 公众号
+
+如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
+
+**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取!
+
+**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
+
+
\ No newline at end of file
From bb148aad1b04ed84d135d92d73f0bc03798e7e57 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Mon, 17 Jun 2019 09:46:30 +0800
Subject: [PATCH 23/25] Update
JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
---
.../JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
index b1ee88a4e00..474b214c545 100644
--- a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
+++ b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
@@ -1,4 +1,4 @@
-点击关注[公众号](#公众号)免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
+点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
From 6990d76fb9d135069a0dadc8620503b8a62fc3b4 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Mon, 17 Jun 2019 10:09:09 +0800
Subject: [PATCH 24/25] Update:optimize content
---
...urrencyAdvancedCommonInterviewQuestions.md | 34 ++++++++++++-------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
index ba1869d0b98..23c7a518c4d 100644
--- a/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
+++ b/docs/java/Multithread/JavaConcurrencyAdvancedCommonInterviewQuestions.md
@@ -1,3 +1,5 @@
+点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
+
- [Java 并发进阶常见面试题总结](#java-并发进阶常见面试题总结)
@@ -116,7 +118,7 @@ public class SynchronizedDemo {
通过 JDK 自带的 javap 命令查看 SynchronizedDemo 类的相关字节码信息:首先切换到类的对应目录执行 `javac SynchronizedDemo.java` 命令生成编译后的 .class 文件,然后执行`javap -c -s -v -l SynchronizedDemo.class`。
-
+
从上面我们可以看出:
@@ -133,7 +135,7 @@ public class SynchronizedDemo2 {
```
-
+
synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的确实是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法,JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。
@@ -176,13 +178,13 @@ synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团
在 JDK1.2 之前,Java的内存模型实现总是从**主存**(即共享内存)读取变量,是不需要进行特别的注意的。而在当前的 Java 内存模型下,线程可以把变量保存**本地内存**比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成**数据的不一致**。
-
+
要解决这个问题,就需要把变量声明为**volatile**,这就指示 JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。
说白了, **volatile** 关键字的主要作用就是保证变量的可见性然后还有一个作用是防止指令重排序。
-
+
### 2.2. 说说 synchronized 关键字和 volatile 关键字的区别
@@ -325,7 +327,7 @@ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
`ThreadLocalMap`是`ThreadLocal`的静态内部类。
-
+
### 3.4. ThreadLocal 内存泄露问题
@@ -383,7 +385,7 @@ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
> - **CachedThreadPool 和 ScheduledThreadPool** : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。
**方式一:通过构造方法实现**
-
+
**方式二:通过Executor 框架的工具类Executors来实现**
我们可以创建三种类型的ThreadPoolExecutor:
@@ -392,7 +394,7 @@ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
- **CachedThreadPool:** 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
对应Executors工具类中的方法如图所示:
-
+
## 5. Atomic 原子类
@@ -405,7 +407,7 @@ Atomic 翻译成中文是原子的意思。在化学上,我们知道原子是
并发包 `java.util.concurrent` 的原子类都存放在`java.util.concurrent.atomic`下,如下图所示。
-
+
### 5.2. JUC 包中的原子类是哪4类?
@@ -504,7 +506,7 @@ CAS的原理是拿期望的值和原本的一个值作比较,如果相同则
AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。
-
+
AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的ReentrantLock,Semaphore,其他的诸如ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基于AQS的。当然,我们自己也能利用AQS非常轻松容易地构造出符合我们自己需求的同步器。
@@ -518,8 +520,6 @@ AQS 原理这部分参考了部分博客,在5.2节末尾放了链接。
#### 6.2.1. AQS 原理概览
-
-
**AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。**
> CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node)来实现锁的分配。
@@ -527,7 +527,7 @@ AQS 原理这部分参考了部分博客,在5.2节末尾放了链接。
看个AQS(AbstractQueuedSynchronizer)原理图:
-
+
AQS使用一个int成员变量来表示同步状态,通过内置的FIFO队列来完成获取资源线程的排队工作。AQS使用CAS对该同步状态进行原子操作实现对其值的修改。
@@ -613,3 +613,13 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
- http://www.cnblogs.com/waterystone/p/4920797.html
- https://www.cnblogs.com/chengxiao/archive/2017/07/24/7141160.html
-
+
+## 公众号
+
+如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
+
+**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"面试突击"** 即可免费领取!
+
+**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
+
+
\ No newline at end of file
From 96aaee0db309b8746c94520212c3036729fddb57 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Mon, 17 Jun 2019 10:09:16 +0800
Subject: [PATCH 25/25] Update
JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
---
.../JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
index 474b214c545..c96bc86dbba 100644
--- a/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
+++ b/docs/java/Multithread/JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md
@@ -308,7 +308,7 @@ new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启
如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
-**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取!
+**《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"面试突击"** 即可免费领取!
**Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。