Java面试题

目录

1... JAVA系列... 10

1.1                 常用容器... 10

1.2                 ArrayList 和 linkedlist 区别。ArrayList 是否会越界... 12

1.3                 ArrayList 和 hashset 的区别。hashset 存的数是否有序。... 12

1.4                 HashMap与HashTable的区别... 13

1.5                 如何决定使用 HashMap 还是 TreeMap. 13

1.6                 HashMap 的实现原理... 14

1.7                 HashSet 的实现原理... 14

1.8                 Iterator怎么使用?有什么特点?... 14

1.9                 Iterator和Listlterator有什么区别?... 15

1.10               volatile 和 synchronized 区别... 15

1.11               synchronized 和 Lock 有什么区别?... 15

1.12               多态的原理... 15

1.13               反射... 16

1.14               队列... 16

1.15               基于数组的循环队列实现... 17

1.16               接口幂等性... 17

1.17               多线程系列... 19

1.17.1            Java 线程间实现同步... 19

1.17.2            notify()与 notifyAll()的区别... 19

1.17.3            创建线程池有哪几种方式?... 20

1.17.4            如何创建线程池?... 20

1.17.5            ThreadPoolExecutor机制... 21

1.17.5.1      概述... 21

1.17.5.2      核心构造方法讲解... 21

1.17.5.3      重点讲解:... 21

1.17.5.4      线程池的运作流程... 22

1.18               JVM系列... 23

1.18.1            JVM 的主要组成部分及其作用... 23

1.18.2            JVM包含两个子系统和两个组件: 23

1.18.3            作用 :... 24

1.18.4            深拷贝和浅拷贝... 25

1.18.5            Java会存在内存泄漏... 25

1.18.6            强引用、软引用、弱引用、虚引用... 26

1.18.7            堆栈的区别... 29

1.18.8            判断对象是否可以被回收... 29

1.18.9            分代垃圾回收器工作原理... 30

1.18.10          JVM 的垃圾回收算法... 32

1.18.11          G1垃圾回收过程... 33

1.18.11.1    Remembered Set 35

2... 框架... 36

2.1                 Spring家族... 36

2.1.1              SpringMVC系列... 36

2.1.1.1        SpringMVC运行流程描述... 36

2.1.1.2        Springmvc的优点: 37

2.1.1.3        SpringMVC常用的注解... 37

2.1.1.4        SpringMVC怎么样设定重定向和转发的?... 37

2.1.1.5        如何解决POST请求中文乱码问题,GET的又如何处理呢?... 38

2.1.1.6        Spring MVC的异常处理 ?... 39

2.1.1.7        SpringMvc的控制器是不是单例模式,有什么问题,怎么解决?... 39

2.1.1.8        在拦截请求中,我想拦截get方式提交的方法,怎么配置?... 39

2.1.1.9        怎样在方法里面得到Request,或者Session?... 39

2.1.1.10      前台有很多个参数传入,并且这些参数都是一个对象的,怎样快速得到这个对象?    39

2.1.1.11      SpringMvc中函数的返回值是什么?... 39

2.1.1.12      SpringMvc用什么对象从后台向前台传递数据的?... 39

2.1.1.13      怎么样把ModelMap里面的数据放入Session里面?... 39

2.1.1.14      SpringMvc里面拦截器是怎么写的:... 40

2.1.1.1        拦截器... 40

2.1.1.2        过滤器... 40

2.1.1.3        拦截器和过滤器的区别:... 41

2.1.2              Spring系列... 43

2.1.2.1        Spring是什么?. 43

2.1.2.2        Spring 的优点?... 43

2.1.2.3        Spring的AOP理解:... 43

2.1.2.4        Spring AOP中的动态代理... 44

2.1.2.5        Spring的IoC理解:... 44

2.1.2.6        BeanFactory和ApplicationContext有什么区别?... 45

2.1.2.7        Spring Bean的生命周期?... 46

2.1.2.8        解释Spring支持的几种bean的作用域。... 47

2.1.2.9        Spring框架中的单例Beans是线程安全的么?... 47

2.1.2.10      Spring如何处理线程并发问题?... 47

2.1.2.11      Spring基于xml注入bean的几种方式:... 48

2.1.2.12      Spring的自动装配:... 48

2.1.2.13      @Autowired和@Resource之间的区别... 49

2.1.2.14      常用注解... 50

2.1.2.15      Spring 框架中都用到了哪些设计模式?... 50

2.1.2.16      Spring事务的实现方式和实现原理:... 51

2.1.2.17      Spring框架中有哪些不同类型的事件?... 52

2.1.2.18      解释一下Spring AOP里面的几个名词:... 52

2.1.2.19      Spring通知有哪些类型?... 53

2.1.3              SpringBoot系列... 55

2.1.3.1        什么是 Spring Boot?... 55

2.1.3.2        Spring Boot 有哪些优点?... 55

2.1.3.3        Spring Boot Starter 的工作原理... 55

2.1.3.4        Spring Boot 中的监视器是什么?... 55

2.1.3.5        运行 Spring Boot有哪几种方式?... 55

2.1.3.6        如何在自定义端口上运行 Spring Boot 应用程序?... 56

2.1.3.7        如何使用 Spring Boot 实现异常处理?... 56

2.1.3.8        如何使用 Spring Boot 实现分页和排序?... 56

2.1.3.9        什么是 JavaConfig?... 56

2.1.3.10      Spring Boot 的核心注解是哪个?主要由哪几个注解组成?... 57

2.1.3.11      Spring Boot 自动配置原理是什么?... 57

2.1.3.12      如何理解 Spring Boot 配置加载顺序?... 58

2.1.3.13      什么是 YAML?... 59

2.1.3.14      YAML 配置的优势在哪里 ?. 59

2.1.3.15      Spring Boot 是否可以使用 XML 配置 ?. 59

2.1.3.16      application和properties 有何区别 ?. 59

2.1.3.17      spring boot 核心的两个配置文件:... 59

2.1.3.18      什么是 Spring Profiles?... 60

2.1.3.19      如何实现 Spring Boot 应用程序的安全性?... 60

2.1.3.20      比较一下 Spring Security 和 Shiro 各自的优缺点 ?. 60

2.1.3.21      Spring Boot 中如何解决跨域问题 ?. 61

2.1.3.22      什么是 CSRF 攻击?... 62

2.1.3.23      Spring Boot 中的监视器是什么?... 62

2.1.3.24      如何在 Spring Boot 中禁用 Actuator 端点安全性?... 62

2.1.3.25      我们如何监视所有 Spring Boot 微服务?... 62

2.1.3.26      什么是 WebSockets?... 62

2.1.3.27      什么是 Spring Data ?. 63

2.1.3.28      SpringData 项目所支持的关系数据存储技术:... 63

2.1.3.29      什么是 Spring Batch?... 63

2.1.3.30      什么是 FreeMarker 模板?... 63

2.1.3.31      如何集成 Spring Boot 和 ActiveMQ?... 63

2.1.3.32      什么是 Apache Kafka?... 64

2.1.3.33      什么是 Swagger?你用 Spring Boot 实现了它吗?... 64

2.1.3.34      前后端分离,如何维护接口文档 ?. 64

2.1.3.35      Spring Boot项目如何热部署?... 64

2.1.3.36      使用了哪些 starter maven 依赖项?... 64

2.1.3.37      Spring Boot 中的 starter 到底是什么 ?. 65

2.1.3.38      spring-boot-starter-parent 有什么用 ?. 65

2.1.3.39      Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?. 65

2.1.3.40      运行 Spring Boot 有哪几种方式?... 65

2.1.3.41      Spring Boot 需要独立的容器运行吗?... 66

2.1.3.42      开启 Spring Boot 特性有哪几种方式?... 66

2.1.3.43      微服务中如何实现 session 共享 ?. 66

2.1.3.44      如何使用 Spring Boot 实现异常处理?... 66

2.1.3.45      如何使用 Spring Boot 实现分页和排序?... 66

2.1.3.46      Spring Boot 中如何实现定时任务 ?. 66

2.1.4              SpringCloud系列... 67

2.1.4.1        什么是 SpringCloud. 67

2.1.4.2        SpringBoot和SpringCloud. 67

2.1.4.3        SpringCloud和Dubbo. 67

2.1.4.4        Rest和RPC对比... 68

2.1.4.5        SpringCloud的核心组件... 68

2.1.4.6        SpringCloud架构原理:... 69

2.1.4.7        Zuul网关功能... 69

2.1.4.8        springcloud如何实现服务的注册?. 69

2.1.4.9        Eureka的服务注册与发现... 69

2.1.4.10      Eureka的我保护模式... 70

2.1.4.11      Eureka和ZooKeeper的区别... 70

2.1.4.12      负载均衡的意义是什么?. 71

2.1.4.13      ribbon的负载均衡策略... 71

2.1.4.14      什么是feigin?它的优点是什么?... 72

2.1.4.15      Ribbon和Feign的区别... 72

2.1.4.16      什么是Hystrix. 72

2.1.4.17      雪崩效应... 73

2.1.4.18      Hystrix的服务熔断和服务降级... 73

2.1.4.19      Hystrix断路器的作用... 73

2.1.4.20      微服务之间是如何独立通讯的... 74

2.1.4.21      微服务的优缺点? 说下在项目开发中碰到的坑... 74

2.1.4.22      你所知道的微服务技术栈... 75

2.1.4.23      什么是Spring Cloud Bus. 75

2.1.4.24      什么是SpringCloudConfig. 75

2.2                 数据库系列... 76

2.2.1              基础... 76

2.2.1.1        数据库三范式:... 76

2.2.1.2        SQL优化... 76

2.2.1.3        索引具体采用的哪种数据结构... 77

2.2.1.4        hash索引和btree索引的区别... 77

2.2.1.5        建立索引的规则:... 79

2.2.1.6        创建索引... 79

2.2.1.7        防止SQL注入四的种方法... 80

2.2.2              Mybatis系列... 81

2.2.2.1        什么是Mybatis?... 81

2.2.2.2        Mybaits的优缺点:... 81

2.2.2.3        MyBatis框架适用场合:... 82

2.2.2.4        MyBatis与Hibernate的区别... 82

2.2.2.5        #{}和${}的区别是什么?... 82

2.2.2.6        当实体类中的属性名和表中的字段名不一样 ,怎么办 ?... 82

2.2.2.7        模糊查询like语句该怎么写?. 83

2.2.2.8        通常一个Xml映射文件,都会写一个Dao接口与之对应,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?... 84

2.2.2.9        Mybatis是如何进行分页的?分页插件的原理是什么?... 84

2.2.2.10      Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?        84

2.2.2.11      如何执行批量插入... 85

2.2.2.12      如何获取自动生成的(主)键值?. 86

2.2.2.13      在mapper中如何传递多个参数?. 86

2.2.2.14      一对一、一对多的关联查询... 88

2.2.2.15      MyBatis实现一对一有几种方式,具体怎么操作... 89

2.2.2.16      MyBatis实现一对多有几种方式,怎么操作... 89

2.2.2.17      Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?        89

2.2.2.18      Mybatis是否支持延迟加载?它的实现原理是什么?... 89

2.2.2.19      Mybatis的一级、二级缓存... 90

2.2.2.20      什么是MyBatis的接口绑定?有哪些实现方式?... 90

2.2.2.21      使用MyBatis的mapper接口调用时有哪些要求?... 91

2.2.2.22      MyBatis面向Mapper编程工作原理... 91

2.2.2.23      Mybatis的Executor执行器之间有什么区别... 91

2.2.2.24      Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?... 92

2.2.3              Redis 的数据结构... 93

2.2.3.1        redis中的五种常用类型... 93

2.2.3.2        缓存穿透... 97

2.2.3.3        缓存击穿... 97

2.2.3.4        缓存雪崩... 98

2.2.3.5        数据库和缓存一致性... 101

2.2.3.6        4种相关模式... 102

2.2.3.7        Redis更新... 104

2.2.4              MySQL数据库引擎 Innodb 和 myisam 区别... 105

2.2.5              数据库的悲观锁和乐观锁应用场景... 106

2.2.6              海量数据过滤(100亿),黑名单过滤一个 url。... 107

3... 设计模式... 108

3.1                 设计模式的六大原则... 108

3.1.1              开放封闭原则(Open Close Principle):... 108

3.1.2              里氏代换原则(Liskov Substitution Principle):... 108

3.1.3              依赖倒转原则(Dependence Inversion Principle)... 108

3.1.4              接口隔离原则(Interface Segregation Principle)... 109

3.1.5              迪米特法则(最少知道原则)(Demeter Principle)... 109

3.1.6              单一职责原则(Principle of single responsibility)... 109

3.2                 单例模式... 110

3.2.1              懒汉式 线程不安全... 111

3.2.2              懒汉式 线程安全... 112

3.2.3              饿汉式 线程安全... 112

3.2.4              静态内部类方式 线程安全... 113

3.2.5              枚举单例 线程安全: 114

3.3                 工厂模式... 115

3.3.1              工厂模式好处... 115

3.3.2              工厂模式分类... 115

3.3.3              简单工厂... 116

3.3.4              工厂方法模式... 117

3.3.5              抽象工厂模式... 118

3.4                 代理模式... 119

3.4.1              什么是代理模式... 119

3.4.2              代理模式应用场景... 119

3.4.3              代理的分类... 119

3.4.4              三种代理的区别... 119

3.5                 建造者模式... 121

3.6                 模板方法模式... 121

3.7                 外观模式... 121

3.8                 原型模式... 121

3.9                 策略模式... 121

3.10               观察者模式... 121

4... 网络连接... 123

4.1                 http 和 https 的区别... 123

4.2                 七层模型各部分作用... 123

4.3                 三次握手... 124

4.4                 四次挥手... 127

4.5                 什么是 WebSockets?... 129

5... 数据结构... 130

5.1                 二叉查找树(BST):不平衡... 130

5.2                 平衡二叉树(AVL):旋转耗时... 130

5.3                 红黑树:树太高... 131

5.4                 B+树... 132

6... 运维... 133

6.1                 Kubernetes (K8S) 133

6.2                 Docker 135

  1. JAVA系列

    1. 常用容器

比较

List

Set

Map

继承接口

Collection

Collection

常见实现类

AbstractList(其常用子类有ArrayList、LinkedList、Vector)

AbstractSet(其常用子类有HashSet、LinkedHashSet、TreeSet)

HashMap、HashTable

常见方法

add( )、remove( )、clear( )、get( )、contains( )、size( )

add()、remove()、clear()、contains( )、size()

put( )、get( )、remove( )、clear( )、containsKey( )、containsValue( )、keySet( )、values( )、size( )

元素

可重复

不可重复(用equals()判断)

不可重复

顺序

有序

无序(实际上由HashCode决定)

线程安全

Vector线程安全

Hashtable线程安全

    1. ArrayList 和 linkedlist 区别。ArrayList 是否会越界

1、ArrayList的实现是基于数组,LinkedList的实现是基于双向链表。(两者均非线程安全)

2、对于随机访问,ArrayList效率优于LinkedList。因为ArrayList直接通过数组下标找到元素;LinkedList要移动指针遍历每个元素直到找到为止

3、对于插入和删除操作,LinkedList效率优于ArrayList。因为ArrayList新增和删除元素时,可能扩容和复制数组;LinkedList实例化对象需要时间外,只需要修改指针即可。

4、LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素

ArrayList自动扩容、没有长度限制

越界异常都发生在数组扩容之时,分别为10、15、22、33、49和73。数组的自动扩容机制,数组初始长度为10,第一次扩容为15=10+10/2,第二次扩容22=15+15/2,第三次扩容33=22+22/2...以此类推

当添加一个元素的时候,它可能会有两步来完成:1. 在 elementData[Size] 的位置存放此元素;2. 增大 Size 的值。

证明:两个线程a和b;当集合中已经添加了14个元素时,一个线程率先进入add()方法,在执行ensureCapacityInternal(size + 1)时,发现还可以添加一个元素,故数组没有扩容,但随后该线程被阻塞在此处。接着另一线程进入add()方法,执行ensureCapacityInternal(size + 1),由于前一个线程并没有添加元素,故size依然为14,依然不需要扩容,所以该线程就开始添加元素,使得size++,变为15,数组已经满了。而刚刚阻塞在elementData[size++] = e;语句之前的线程开始执行,它要在集合中添加第16个元素,而数组容量只有15个,所以就发生了数组下标越界异常!

    1. ArrayList 和 hashset 的区别。hashset 存的数是否有序。
  1. HashSet实现Set接口,ArrayList实现List接口,Set和List接口都实现Collection接口;
  2. list集合内的元素是有序的,元素可以重复,查询效率高,增删效率低;set元素无序且不可重复,是散列结构(通过散列表:散列单元指向链表)。
  3. HashSet与ArrayList均线程不安全
  4. ArrayList是一个有顺序的数组,每次放入其中的都是对象的引用,可重复放入。
  5. HashSet是一个无序集合,每次放入一个新的元素,都会对其进行检查对象是否存在,如果存在则不会放入。

HashSet、ArrayList、LinkedList使用add()方法将元素放入集合中,HashMap使用put()方法将元素放入map中

    1. HashMap与HashTable的区别
  1. HashMap线程不安全,HashTable线程安全,由于HashMap非线程安全,效率上可能高于Hashtable。
  2. HashMap、Hashtable不保证插入顺序,但是循环遍历时,输出顺序是不会改变的。
  3. HashMap是Hashtable的轻量级实现(非线程安全的实现),都实现了Map接口。 
  4. HashMap不能包含重复键,但可以包含重复值。
  5. HashMap允许null key和null value,而hashtable不允许。
  6. HashMap去掉了Hashtable中的contains方法,都提供的有containsvalue和containsKey方法。

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。

    1. 如何决定使用 HashMap 还是 TreeMap
  1. HashMap: 适用于在Map中插入、删除和定位元素。Treemap: 适用于按自然顺序或自定义顺序遍历键(key)。
  2. HashMap 通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap.
  3. HashMap 非线程安全 TreeMap 非线程安全
  4.  
    HashMap的结果是没有排序的,而TreeMap输出的结果是排好序的。

HashMap的键的性质-它通常是一个简单的String甚至是一个数字。

而 String和Integer的计算哈希码的速度 比 整个对象的默认哈希码 计算要快得多;换句话说:

如果HashMap的键与存储在HashSet中的键是相同的对象,则性能将没有真正的区别。区别在于HashMap的键是哪种对象

    1. HashMap 的实现原理

HashMap概述:HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashMap的数据结构:在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根据hash值得到这个元素在数组中的位置(下标),如果该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。

需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

    1. HashSet 的实现原理
  1. HashSet底层由HashMap实现
  2. HashSet的值存放于HashMap的key上
  3. HashMap的value统一为null
    1. Iterator怎么使用?有什么特点?

Java中lterator功能比较简单,并且只能单向移动:

  1. 使用方法iterator()要求容器返回一个Iterator,第一次調用Iterator的next()方法时,它返回序列的第一个元素,注意: iterator()方法是java.lang.lterable接口,被Collection继承

(2)使用next()获得序列中的下一个元素.

(3)使用hasNext()检查序列中是否还有元素.

(4)使用remove()将迭代器新返回的元素删除.

Iterator是Java迭代器最简单的实现,为List设计的Listlterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素

    1. Iterator和Listlterator有什么区别?
  1. Iterator可用来過历Set和List集合,但是Listterator只能用来這历List
  2. Iterator对集合只能是前向遍历, Listtierator可以前向也可以后向.
  3. ListIterator实现了Iterator接口,井包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等
    1. volatile 和 synchronized 区别
  1. volatile本质是告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别
  3. volatile仅能实现变量的修改可见性,不能保证原子性(同生共死);而synchronized则可以保证变量的修改可见性和原子性
  4. volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  5. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
    1. synchronized 和 Lock 有什么区别?
  1. 首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
  2. synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
  3. synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
  4. 用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
  5. Lock锁适合大量代码的同步问题,synchronized锁适合少量代码的同步问题。
    1. 多态的原理

多态性:顾名思义就是拥有“多种形态”的含义,是指属性或方法在子类中表现为多种形态。(重写,重载  是多态的体现)

多态指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

抽象类和接口区别

1 .   接口中的方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),当然在jdk8中可以有default修饰的方法。 但是default修饰的方法也是且只能是public的。 jdk1.8之后允许接口中有静态方法,但是静态方法的访问修饰符也必须public,且默认省略就是public。 接口的访问修饰符必须是public,且省略就是public (这是在接口在单个文件中);接口如果定义在其他的文件中,缺省的时候就是包访问权限。抽象类可以包含普通方法。

2.    接口只能定义静态常量属性 (接口中的变量会被隐式的指定为 public static final 变量),抽象类既可以定义普通属性,也可以定义静态常量属性。

3 .   接口不包含构造方法,抽象类里可以包含构造方法。

4.   抽象类不能被实例化,但不代表它不可以有构造函数,抽象类可以有构造函数,备继承类扩充

5.   接口是核心,其定义了要做的事情,包含了许多的方法,但没有定义这些方法应该如何做。

6.    如果许多类实现了某个接口,那么每个类都要用代码实现那些方法

7.   如果某一些类的实现有共通之处,则可以抽象出来一个抽象类,让抽象类实现接口的公用的代码,而那些个性化的方法则由各个子类去实现。

死锁的原因

主要是:(1) 因为系统资源不足。(2) 进程运行推进的顺序不合适。(3) 资源分配不当等。如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

产生死锁的四个必要条件:(1) 互斥条件:一个资源每次只能被一个进程使用。(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立

    1. 反射

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力

Java反射:

在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法

Java反射机制主要提供了以下功能:

  1. 在运行时判断任意一个对象所属的类。
  2. 在运行时构造任意一个类的对象。
  3. 在运行时判断任意一个类所具有的成员变量和方法。
  4. 在运行时调用任意一个对象的方法。 
    1. 队列

   
 队列是只允许在一端插入数据操作,在另一端进行删除数据操作的特殊线性表;进行插入操作的一端称为队尾(入队列),进行删除操作的一端称为队头(出队列);队列具有先进先出(FIFO)的特性。

队列通常提供的操作:

入队: 通常命名为push() ;  出队: 通常命名为pop()  ; 求队列中元素个数

判断队列是否为空;  获取队首元素。

    1. 基于数组的循环队列实现

 
以数组作为底层数据结构时,一般讲队列实现为循环队列。这是因为队列在顺序存储上的不足:每次从数组头部删除元素(出队)后,需要将头部以后的所有元素往前移动一个位置,这是一个时间复杂度为O(n)的操作:

    1. 接口幂等性

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条...,这就没有保证接口的幂等性

查询、删除操作是天然的幂等操作。

两种实现方案:  1. 通过代码逻辑判断实现    2. 使用token机制实现  

  1. 通过代码逻辑判断实现:

   通过一个中间字段进行判断;例如订单操作,orderStatus 处于01两种状态时,对订单执行0->1 的状态流转操作应该是具有幂等性的。这时候需要在执行update操作之前检测orderStatus是否已经=1,如果已经=1则直接返回true即可。

  1. 使用token机制实现:

1. 生成全局唯一的token,token放到redisjvm内存,token会在页面跳转时获取.存放到pageScope,支付请求提交先获取token

 2. 提交后后台校验token,执行提交逻辑,提交成功同时删除token,生成新的token更新redis ,这样当第一次提交后token更新了,页面再次提交携带的token是已删除的token后台验证会失败不让提交

  token特点:   要申请,一次有效性,可以限流

     注意: redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,存在并发问题,不建议使用

    1. 多线程系列
      1. Java 线程间实现同步

使用  synchronized关键字或lock()锁  实现多线程步;

synchronized: 具有原子性,有序性和可见性; volatile:具有有序性和可见性

原子性:

是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。在多线程情况下,提供互斥访问,同一时刻只能有一个线程对数据进行操作。

可见性:

是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。

有序性:

在本线程内观察,所有操作都是有序的(即指令重排不会导致单线程程序执行结果与排序前有任何差别)。在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。在 Java 内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。Volatile能避免重排序,确保有序性

      1. notify()与 notifyAll()的区别

调用了notify后只有一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。

创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

  • newCachedThreadPool()

创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。

  • newSingleThreadExecutor()

这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。

  • newScheduledThreadPool(int corePoolSize)

创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

      1. 如何创建线程池?

《阿里巴巴Java开发手册》中强制线程池不允许使用 Executors 去创建,而是通过 new ThreadPoolExecutor 实例的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险

Executors 返回线程池对象的弊端如下:

FixedThreadPool 和 SingleThreadExecutor :

允许请求的队列长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致OOM。+

CachedThreadPool 和 ScheduledThreadPool :

允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。

 OOM:全称“Out Of Memory”,来源于java.lang.OutOfMemoryError。官方说明: Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector. 意思就是说,当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error(注:非exception,因为这个问题已经严重到不足以被应用处理)。

      1. ThreadPoolExecutor机制
        1. 概述

1、ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程调度,线程池管理等等服务;

        1. 核心构造方法讲解

下面是ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueueThreadFactory threadFactory)核心的构造参数讲解

corePoolSize                核心线程池大小

maximumPoolSize       最大线程池大小

keepAliveTime               线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间

TimeUnit                       keepAliveTime时间单位

workQueue                    阻塞任务队列

threadFactory                新建线程工厂

RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理

        1. 重点讲解:

比较容易误解的是:corePoolSize,maximumPoolSize,workQueue之间关系。

1.     当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。

2.    当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行

3.     当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务

4.   当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理

5.      当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程

6.       当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

        1. 线程池的运作流程

    1. JVM系列
      1.  
        JVM 的主要组成部分及其作用
      2. JVM包含两个子系统和两个组件:

两个子系统Class loader(类装载)Execution engine(执行引擎)

两个组件Runtime data area(运行时数据区)Native Interface(本地接口)

Class loader(类装载)根据给定的全限定类名(如:java.lang.Object)来装载class文件到Runtime data area中的method area。

Execution engine(执行引擎):执行classes中的指令。

Native Interface(本地接口):与native libraries交互,是其它编程语言交互的接口。

Runtime data area(运行时数据区域):这就是我们常说的JVM的内存。

      1. 作用 :

首先通过编译器把 Java 代码转换成字节码;类加载器(ClassLoader)再把字节码加载到内存中,将其放在运行时数据区(Runtime data area)的方法区内,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。下图为Java程序运行机制详细说明

类的加载是指将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。

程序计数器(Program Counter Register):当前线程所执行字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;

Java 虚拟机栈(Java Virtual Machine Stacks)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QY别说话

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值