Java面试宝典:掌握高级技巧,征服职场殿堂(怒肝88小时整理合集)

目录

一、Java 基础

1.JDK 和 JRE 有什么区别?

2.== 和 equals 的区别是什么?

3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

4.final 在 java 中有什么作用?  (在 Java 中 final 可以修饰类、变量、方法)

5.java 中的 Math.round(-1.5) 等于多少?

6.String 属于基础的数据类型吗?  (引用数据类型)

1 、字符类型: char  

2 、基本整型:byte,short,int,long  

3 、浮点型:float,double 

4 布尔类型:boolean”

7.java  中操作字符串都有哪些类? (String、 StringBuffer、 StringBuilder)它们之间有什么区别?

8.Stringstr="i"与 Stringstr=new String(“i”)一样吗?

9.如何将字符串反转?

10.String 类的常用方法都有那些?

11.抽象类必须要有抽象方法吗?

12.普通类和抽象类有哪些区别?

13.抽象类能使用 final 修饰吗?

14.接口和抽象类有什么区别?

15.java 中 IO 流分为几种?

16.BIO、 NIO、AIO 有什么区别?

17.Files 的常用方法都有哪些?

二、容器

18.java 容器都有哪些?

19.Collection 和 Collections 有什么区别?

20.List、Set、Map 之间的区别是什么?

21.HashMap 和 Hashtable 有什么区别?

22.如何决定使用 HashMap 还是 TreeMap?

23.说一下 HashMap 的实现原理?

24.说一下 HashSet 的实现原理?

25.ArrayList 和 LinkedList 的区别是什么?

26. 如何实现数组和 List 之间的转换?

27.ArrayList 和 Vector 的区别是什么?

28.Array 和 ArrayList 有何区别?

29.在 Queue 中 poll()和 remove()有什么区别?

30.哪些集合类是线程安全的?

31.迭代器 Iterator 是什么?

32.Iterator 怎么使用?有什么特点?

33.Iterator 和 ListIterator 有什么区别?

34.怎么确保一个集合不能被修改?

三、多线程

35.并行和并发有什么区别?

36.线程和进程的区别?

37.守护线程是什么?

38.创建线程有哪几种方式?

39.说一下 runnable 和 callable 有什么区别?

40.线程有哪些状态?

41.sleep() 和 wait() 有什么区别?

42.notify()和 notifyAll()有什么区别?

43.线程的 run()和 start()有什么区别?

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

45.线程池都有哪些状态?

46.线程池中 submit()和 execute()方法有什么区别?

47.在 java 程序中怎么保证多线程的运行安全?

48.多线程锁的升级原理是什么?

49.什么是死锁?

50.怎么防止死锁?

51.ThreadLocal 是什么?有哪些使用场景?

52.说一下 synchronized 底层实现原理?

53.synchronized 和 volatile 的区别是什么?

54.synchronized 和 Lock 有什么区别?

55.synchronized 和 ReentrantLock 区别是什么?

56.说一下 atomic 的原理?

四、反射

57.什么是反射?

58.什么是 java 序列化?什么情况下需要序列化?

59.动态代理是什么? 有哪些应用?

60.怎么实现动态代理?

五、对象拷贝

61.为什么要使用克隆?

63.深拷贝和浅拷贝区别是什么?

六、 Java Web

64.jsp 和 servlet 有什么区别?

65.jsp 有哪些内置对象?作用分别是什么?

66.说一下 jsp 的 4 种作用域?

67.session 和 cookie 有什么区别?

68.说一下 session 的工作原理?

69.如果客户端禁止 cookie 能实现 session 还能用吗?

70.spring mvc 和 struts 的区别是什么?

71.如何避免 sql 注入?

72.什么是 XSS 攻击, 如何避免?

73.什么是 CSRF 攻击,如何避免? 

七、异常

74.throw 和 throws 的区别?

75.fifinal、fifinally、fifinalize 有什么区别?

76.try-catch-fifinally 中哪个部分可以省略?

77.try-catch-fifinally 中,如果 catch 中 return 了, fifinally 还会执行吗?

78.常见的异常类有哪些?

八、网络

79.http 响应码 301 和 302 代表的是什么?  有什么区别?

80.forward 和 redirect 的区别?

81.简述 tcp 和 udp 的区别?

82.tcp 为什么要三次握手,两次不行吗?为什么?

83.说一下 tcp 粘包是怎么产生的?

84.OSI 的七层模型都有哪些?

85.get 和 post 请求有哪些区别?

86.如何实现跨域?

87.说一下 JSONP 实现原理?

九、设计模式

88.说一下你熟悉的设计模式?

89.简单工厂和抽象工厂有什么区别?

十、 Spring/Spring MVC

90.为什么要使用 spring?

91.解释一下什么是 aop?

92.解释一下什么是 ioc?

93.spring 有哪些主要模块?

94.spring 常用的注入方式有哪些?

95.spring 中的 bean 是线程安全的吗?

96.spring 支持几种 bean 的作用域?

97.spring 自动装配 bean 有哪些方式?

98.spring 事务实现方式有哪些?

99.说一下 spring 的事务隔离?

100.说一下 spring mvc 运行流程?

101.spring mvc 有哪些组件?

102.@RequestMapping 的作用是什么?

103.@Autowired 的作用是什么?

十一、Spring Boot/Spring Cloud

104.什么是 spring boot?

105.为什么要用 spring boot?

106.spring boot 核心配置文件是什么?

107.spring boot 配置文件有哪几种类型?它们有什么区别?

108.spring boot 有哪些方式可以实现热部署?

109.jpa 和 hibernate 有什么区别?

110.什么是 spring cloud?

111.spring cloud 断路器的作用是什么?

112.spring cloud 的核心组件有哪些?

十三、 Mybatis

125.mybatis 中 #{}和 ${}的区别是什么?

127.RowBounds 是一次性查询全部结果吗?为什么?

128.mybatis 逻辑分页和物理分页的区别是什么?

129.mybatis 是否支持延迟加载?延迟加载的原理是什么?

130.说一下 mybatis 的一级缓存和二级缓存?

131.mybatis 和 hibernate 的区别有哪些?

132.mybatis 有哪些执行器(Executor)?

133.mybatis 分页插件的实现原理是什么?

十四、 RabbitMQ

135.rabbitmq 的使用场景有哪些?

136.rabbitmq 有哪些重要的角色?

137.rabbitmq 有哪些重要的组件?

138.rabbitmq 中 vhost 的作用是什么?

139.rabbitmq 的消息是怎么发送的?

140.rabbitmq 怎么保证消息的稳定性?

141.rabbitmq 怎么避免消息丢失?

142.要保证消息持久化成功的条件有哪些?

143.rabbitmq 持久化有什么缺点?

144.rabbitmq 有几种广播类型?

145.rabbitmq 怎么实现延迟消息队列?

146.rabbitmq 集群有什么用?

147.rabbitmq 节点的类型有哪些?

148.rabbitmq 集群搭建需要注意哪些问题?

149.rabbitmq 每个节点是其他节点的完整拷贝吗?为什么?

150.rabbitmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?

151.rabbitmq 对集群节点停止顺序有要求吗?

十六、 Zookeeper

157.zookeeper 是什么?

158.zookeeper 都有哪些功能?

159.zookeeper 有几种部署模式?

160.zookeeper 怎么保证主从节点的状态同步?

161.集群中为什么要有主节点?

162.集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?

163.说一下 zookeeper 的通知机制?

十七、 MySql

164.数据库的三范式是什么?

165.一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了 一条数据,此时 id 是几?

166.如何获取当前数据库版本?

167.说一下 ACID 是什么?

168.char 和 varchar 的区别是什么?

169.flfloat 和 double 的区别是什么?  

170.mysql 的内连接、左连接、右连接有什么区别?

171.mysql 索引是怎么实现的?

172.怎么验证 mysql 的索引是否满足需求?

173.说一下数据库的事务隔离?

174.说一下 mysql 常用的引擎?

175.说一下 mysql 的行锁和表锁?

176.说一下乐观锁和悲观锁?

177.mysql 问题排查都有哪些手段?

178.如何做 mysql 的性能优化?

十八、 Redis

179.redis 是什么?都有哪些使用场景? 

180.redis 有哪些功能?

181.redis 和 memecache 有什么区别?

182.redis 为什么是单线程的?

183.什么是缓存穿透? 怎么解决?

184.redis 支持的数据类型有哪些?

185.redis 支持的 java 客户端都有哪些?

186.jedis 和 redisson 有哪些区别?

187.怎么保证缓存和数据库数据的一致性?

189.redis 怎么实现分布式锁?

190.redis 分布式锁有什么缺陷?

192.redis 淘汰策略有哪些?  193.redis 常见的性能问题有哪些?该如何解决?

十九、 JVM

194.说一下 jvm 的主要组成部分?及其作用?

195.说一下 jvm 运行时数据区?

196.说一下堆栈的区别?

197.队列和栈是什么? 有什么区别?

198.什么是双亲委派模型?

199.说一下类加载的执行过程?

200.怎么判断对象是否可以被回收?

201.java 中都有哪些引用类型?

202.说一下 jvm 有哪些垃圾回收算法?

203.说一下 jvm 有哪些垃圾回收器?

204.详细介绍一下 CMS 垃圾回收器?

205.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

206.简述分代垃圾回收器是怎么工作的?

207.说一下 jvm 调优的工具?

208.常用的 jvm 调优的参数都有哪些?

算法题

Linux 常用命令

一、基本命令

二、目录操作命令

三、文件操作命令

四、压缩文件操作

五、查找命令

十、其他命令

十一、高薪挑战宝典

11.1 集合常见的面试题

1. Arraylist 与 LinkedList 区别

2. Collections.sort 和 Arrays.sort 的实现原理

3. HashMap 原理, java8 做了什么改变

4. List 和 Set , Map 的区别

5. poll()方法和 remove()方法的区别?

6. HashMap , HashTable ,ConcurrentHash 的共同点和区别

7. 写一段代码在遍历 ArrayList 时移除一个元素

8. Java 中怎么打印数组?

9. TreeMap 底层?

10. HashMap 的扩容过程

11. HashSet 是如何保证不重复的

12. HashMap 是线程安全的吗, 为什么不是线程安全的? 死循环问题?

13. LinkedHashMap 的应用,底层, 原理

14. 哪些集合类是线程安全的? 哪些不安全?

15. ArrayList 和 Vector 的区别是什么?

16. Collection 与 Collections 的区别是什么?

17. 如何决定使用 HashMap 还是 TreeMap?

19. 迭代器 Iterator 是什么?怎么用,有什么特点?

20. Iterator 和 ListIterator 有什么区别?

21. 怎么确保一个集合不能被修改?

22. 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?

23. 什么是 Java 优先级队列(Priority Queue)?

24. JAVA8 的 ConcurrentHashMap 为什么放弃了分段锁,有什么问题吗, 如果你来设计, 你如何设计。

25. 阻塞队列的实现, ArrayBlockingQueue 的底层实现?

26. Java 中的 LinkedList 是单向链表还是双向链表?

27. 说一说 ArrayList 的扩容机制吧

28. HashMap 的长度为什么是 2 的幂次方, 以及其他常量定义的含义~

29. ConcurrenHashMap 原理? 1.8 中为什么要用红黑树?

30. ArrayList 的默认大小

31. 为何 Collection 不从 Cloneable 和 Serializable 接口继承?

32. Enumeration 和 Iterator 接口的区别?

33. 我们如何对一组对象进行排序?

34. 当一个集合被作为参数传递给一个函数时,如何才可以确保函数不能修改它?

35. 说一下 HashSet 的实现原理?

36. Array 和 ArrayList 有何区别?

37. 为什么 HashMap 中 String、Integer 这样的包装类适合作为 key?

38. 如果想用 Object 作为 hashMap 的 Key?;

39. 讲讲红黑树的特点?

40. Java 集合类框架的最佳实践有哪些?

41.谈谈线程池阻塞队列吧~

42. HashSet 和 TreeSet 有什么区别?

43. Set 里的元素是不能重复的, 那么用什么方法来区分重复与否呢? 是用 ==还是 equals()?

45. HashMap 在 JDK1.7 和 JDK1.8 中有哪些不同?

46. ArrayList 集合加入 1 万条数据, 应该怎么提高效率

47. 如何对 Object 的 list 排序

48. ArrayList 和 HashMap 的默认大小是多数?

49. 有没有有顺序的 Map 实现类,如果有,他们是怎么保证有序的

50. HashMap 是怎么解决哈希冲突的

11.2 线程常见面试题

1、并发编程三要素?

2、实现可见性的方法有哪些?

3、多线程的价值?

4、创建线程的有哪些方式?

5、创建线程的三种方式的对比?

6、线程的状态流转图

7、Java 线程具有五中基本状态

8、什么是线程池?有哪几种创建方式?

9、四种线程池的创建:

10、线程池的优点?

11、常用的并发工具类有哪些?

12、CyclicBarrier 和 CountDownLatch 的区别

13、synchronized 的作用?

14、volatile 关键字的作用

15、什么是 CAS

16、CAS 的问题

17、什么是 Future?

18、什么是 AQS

19、AQS 支持两种同步方式:

20、 ReadWriteLock 是什么

21、 FutureTask 是什么

22、synchronized 和 ReentrantLock 的区别

23、什么是乐观锁和悲观锁

24、线程 B 怎么知道线程 A 修改了变量

25、synchronized、volatile、CAS 比较

26、sleep 方法和 wait 方法有什么区别?

27、ThreadLocal 是什么?有什么用?

28、为什么 wait()方法和 notify()/notifyAll()方法要在同步块中被调用

29、多线程同步有哪几种方法?

30、线程的调度策略

31、ConcurrentHashMap 的并发度是什么

32、 Linux 环境下如何查找哪个线程使用 CPU 最长

33、Java 死锁以及如何避免?

34、死锁的原因

35、怎么唤醒一个阻塞的线程

37、什么是多线程的上下文切换

38、如果你提交任务时, 线程池队列已满,这时会发生什么

39、Java 中用到的线程调度算法是什么

40、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?

41、什么是自旋

42、Java

Concurrency API 中的 Lock 接口(Lock

43、单例模式的线程安全性

44、Semaphore 有什么作用

45、 Executors 类是什么?

46、线程类的构造方法、静态块是被哪个线程调用的

47、同步方法和同步块, 哪个是更好的选择?

48、Java 线程数过多会造成什么异常?

11.3 MySQL 常见面试题

1 事务

2 B 树和 B+树

3 建立索引

4 组合索引(多列索引)

5 聚簇索引和非聚簇索引(针对 B+树索引)

6 数据库引擎(主要就是 MyISAM 和 InnoDB 的区别)

7 主从复制(读写分离、数据备份)


一、Java 基础

1.JDK JRE 有什么区别?

JREJava Runtime Environment)是 Java 运行时环境……它是运行编译后的 Java 程序所必需的一切包,包括 Java 虚拟机(JVM)Java 基础类库、  Java 命令和其他基础设施。但是,它不能用于创建新程序。

JDK Java 开发工具包……功能齐全的 SDKforJava。它拥有 JRE 所拥有的一切, 还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具:  jconsolejvisualvm 等工具软件,还包含了 java 程序编写所需的文档和 demo 例子程序。它能够创建和编译程序,是提供给程序员使用的。

2.== equals 的区别是什么?

1、功能不同

"=="是判断两个变量或实例是不是指向同一个内存空间的值

"equals"是判断两个变量或实例所指向的内存空间的值是不是相同。

2、定义不同

"equals"JAVA 中是一个方法。

"=="JAVA 中只是一个运算符合

(1)  Java 中基本类型变量有 byteshortchar int longfloatdouble boolean,也称为原始数据类型。他们之间的比较应用双等号( ==)比较他们的值,当使用 ==来判断两个变量是否相等时,如果这两个变量是基本数据类型,则只要两个变量值相等就放回 true

(2)  复合数据类型(类)

当使用 ==比较他们两个的值,比较的是他们的变量指向的地址值,除非这两个变量是同一个 NEW 出来的对象,则他们的比较为 true,反之为 false

Equals()方法:

Java 中所有的类都继承与基类 Object,在 Object 中定义了 equals 方法,这个方法的初始行为是比较对象的内存地址。但 是在一些类库中这个方法被重写了,如 String Integer Date 这些类中的 equals 方法有自身的实现,  而不再是比较内地址值。

所有说对用复合型数据类型(引用类型),我们推荐使用重写了的 equals 方法进行比较,

3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

两个对象 equals 相等,则它们的 hashcode 必须相等,反之则不一定。两个对象 ==相等,则其 hashcode一定相等, 反之不一定成立。

hashCode(哈希码值)的存在主要应用于查找的快捷性,如 hashTable hashMap 等,hashCode 码是确定对象在散列存储结构中的地址值。

如果两个对象通过 equals 方法比较相等,那么他们的 hashCode 值也一定相等。反之 hashCode 码相等,但是连个对象的equals比较不一定相等,也就是说这两个对象之间不一定适用于 equals 方法,只能说明这两个对象都存在于散列存储结构中。

4.final  java 中有什么作用?  (在 Java 中 final 可以修饰类、变量、方法)

(1)Final 修饰类:

当用 final 修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用 final 进行修饰。 final 类中的成员变量可以根据需要设为 final,但是要注意 final 类中的所有成员方法都会被隐式地指定为 final 方法。

(2) Final 修饰方法:final 修饰的方法后该方法不能被子类重写(可以重载多个 final 修饰的方法), 意:重写的前提是子类可 以从父类中继承此方法,如果父类中用 final 修饰的方法同时访问修饰符是 private 时,子类中则可以定义相同的方法名和

参数

(3) Final 修饰变量: final 在修饰基本数据类型变量时,该变量一经赋值则不许改变,如果修饰的引用数据类型时,则代表着引用的地址值不能改变,但地址值所指向的内容可以改变。

①修饰成员变量时:修饰成员变量时必须显示初始化,初始化方式有两种,第一就是变量声名时直接初始化,二就是变量声

明后不初始化,但必须要在这个变量所在的类的所有构造函数中对这个变量进行赋值。

②修饰局部变量时:当函数的参数通过 final 进行定义时,代表着该参数为只读,可以读取使用该参数,但不能修改该参数值。

5.java 中的 Math.round(-1.5) 等于多少?

Math round 方法是四舍五入,如果参数是负数,则往大的数如,Math.round(- 1.5)=-1

6.String 属于基础的数据类型吗?  (引用数据类型)

String 并不是基本数据类,  而是一个类(class),C++java 等编程语言中的字符串,

Java 中八大基本类型数据:

1 字符类型: char  
2 基本整型:byte,short,int,long  
3 浮点型:float,double 
4 布尔类型:boolean

7.java  中操作字符串都有哪些类? (String、 StringBuffer、 StringBuilder)它们之间有什么区别?

String : final 修饰,  String 类的方法都是返回 new String。即对 String 对象的任何改变都不影响到原对象,对字符串的修改操作都会生成新的对象。  StringBuffer : 对字符串的操作的方法都加了 synchronized,保证线程安全。

StringBuilder : 不保证线程安全,在方法体内需要进行字符串的修改操作,  可以 new StringBuilder 对象,调用 StringBuilder 象的 append replacedelete 等方法修改字符串。

(1)    String 是不可变字符窜 StringBufferStringBuilder 是可变字符窜。三者的底层都是以 char[]形式保存字符窜 String 底层初始化时默认 char[]数组长度为 0,StringBufferStringBuilder 初始化默认的 char[]数组长度为 16

(因为 String 不可变,每次对 String 进行操作都会生成新的字符窜)

(2)    StringBuffer 中大部分的方法都是被 synchronized 关键字这就代表着 StringBuffer 是线程安全的。   StringBuilder    中的方法则没有,代表着他是一个线程不安全的。所以在单线程的情况下选择 StringBuilder 要更快,然而在多线程当中

考虑使用 StringBuffer 更加安全些

(3)    在生命变量的时候如果根据情况这个变量声明之后基本上不做修改我自己考虑直接使用 String,不同 new String()的

方式进行声明那样就不会再堆内存中创建对象,此时 String 变量直接指向常量池,并且可以复用,效率更高

8.Stringstr="i"Stringstr=new String(“i”)一样吗?

String str =  “i”代表着声明了一个变量 str,此时在常量池中创建了一个内容为 i 的字符窜对象。

String str = new String(“I”);此时代表着创建了两个对象, str 引用地址指向堆内存,如果常量池中没有字符窜 i,则会

在常量池中创建第二个对象字符窜 i。

9.如何将字符串反转?

1. 利用 StringBuffer StringBuilder  reverse 成员方法:

public static String reverse(Stringstr) {

return new StringBuilder(str).reverse().toString();

}

2. 利用 String toCharArray 方法先将字符串转化为 char 类型数组,然后将各个字符进行重新拼接:

//自定义方法

public static String reverse(Stringstr){

char[] chars = str.toCharArray();

//创建StringBuilder 对象进行拼接

StringBuilder builder = new StringBuilder();

for (inti = chars.length - 1; i >= 0; i--) {

builder.append(chars[i]);

}

return builder.toString();

}

3. 利用 String CharAt 方法取出字符串中的各个字符:

public static String reverse1(Stringstr){

//创建StringBuilder 对象进行拼接

StringBuilder builder = new StringBuilder();

//获取字符窜长度

int length = str.length();

for (inti = length-1; i >=0; i--) {

builder.append(str.charAt(i));

}

return builder.toString();

}

4.使用递归的方式进行反转

public static String reverse2(Stringstr){

//获取字符窜长度

int length = str.length();

if(length<=1){

returnstr;

}

String left = str.substring(0, length/2);

String right = str.substring(length/2,length);

return reverse2(right)+reverse2(left);

}

10.String 类的常用方法都有那些?

indexOf(Stringstr):查找指定的字符在当前字符窜第一次出现的索引值

charAt(int index) 返回指定索引处得字符

replace(char oldChar,char newChar) : 它是通过用 newChar 替换此字符串中出现的所有 oldChartrim() 去除字符串两端的空白

split() 分割字符串 返回分割后的字符串数组

getBytes() 返回字符串的 byte 类型数组

length() 返回字符串的长度

toLowerCase() 字符串转小写

toUpperCase() 字符串转大写

substring() 截取字符串

equals() 字符串比较

11.抽象类必须要有抽象方法吗?

抽象类可以没有抽象方法,  但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,  它也不能再实例化,即不能直接构造一个该类的对象。 如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。

12.普通类和抽象类有哪些区别?

抽象类不能被实例化

抽象类可以有抽象方法,抽象方法只需申明,  无需实现

含有抽象方法的类必须申明为抽象类

抽象类的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类

抽象方法不能被声明为静态

抽象方法不能用 private 修饰

抽象方法不能用 final 修饰

13.抽象类能使用 final 修饰吗?

不能,抽象类是被用于继承的, final 修饰代表不可修改、不可继承的。

14.接口和抽象类有什么区别?

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向

实现所有接口方法的类对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,  一

个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,  不能实现,接口是设计的结果 ,抽象类是重构的结果

7、抽象类里可以没有抽象方法

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,  所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单根继承。

15.java IO 流分为几种?

Java 中的流分为两种,  一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个) :InputStream OutputStream  Reader WriterJava 中其他多种多样变化的流均是由它们派生出来的。

16.BIO NIOAIO 有什么区别?

BIO 是一个连接一个线程。   NIO 是一个请求一个线程。  AIO 是一个有效请求一个线程。

BIO:同步并阻塞,  服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如

果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,  多路复用器轮

询到连接有 I/O 请求时才启动一个线程进行处理。

AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的 I/O 请求都是由 OS 先完成了再通知服务器应用去启

动线程进行处理。

17.Files 的常用方法都有哪些?

Files.exists() 检测文件路径是否存在 Files.createFile()创建文件 Files.createDirectory()创建文件夹 Files.delete() 删除文件或者目 Files.copy() 复制文件 Files.move() 移动文件 Files.size()查看文件个数 Files.read() 读取文件 Files.write()写入文件

二、容器

18.java 容器都有哪些?

List,Map,Set Collection  List  LinkedList ArrayList Vector Stack Set Map  Hashtable  HashMap WeakHashMap

数据容器主要分为了两类:   Collection: 存放独立元素的序列。   Map:存放 key-value 型的元素对。(这对于需要利用 key 找 value 的程序十分的重要  从类体系图中可以看出, Collection 定义了 Collection 类型数据的最基本、最共性的功能接口, List 对该接口进行了拓展。 LinkedList :其数据结构采用的是链表,此种结构的优势是删除和添加的效率很高,但随机访问元素时效率较 ArrayList 类低。 ArrayList:其数据结构采用的是线性表,此种结构的优势是访问和查询十分方便,但添加和删除的时候效率很低。 HashSet: Set 类不允许其中存在重复的元素(集),无法添加一个重复的元素(Set 中已经存在)。

HashSet 利用 Hash 函数进行了查询效率上的优化,其 contain  ()方法经常被使用,以用于判断相关元素是否已经被添加过。 HashMap: 提供了 key-value 的键值对数据存储机制,可以十分方便的通过键值查找相应的元素,而且通过 Hash 散列机制,查找十分的方便。

19.Collection Collections 有什么区别?

Collection 是集合的接口,其继承类又 List Set

Collections 是集合的工具类,定义了许多操作集合的静态方法。是帮助类

20.ListSetMap 之间的区别是什么?

List:有序集合

Set:不重复集合, LinkedHashSet 按照插入排序, SortedSet 可排序,  HashSet 无序

Map:键值对集合

(1)元素的重复性:

List 集合中可以出现重复元素

Set 集合中不可以出现重复元素,在向 Set 集合中存储多个重复的元素时会出现覆盖

Map 集合采用 key-value 的形式存储,在 Map 中不能出现重复的 Key 键,但可以出现多个不同的 Key 对应相同的 Value

(2)元素的有序性:

List 集合及其所有的实现类都确保了元素的有序性

Set 集合中的元素是无序的, 但是某些 Set 集合通过特定的形式对其中的元素进行排序,如 LinkedHashSet

Map 和 Set一样对元素进行了无序存储,如:TreeMap 根据 Key 键实现了元素的升序排序

(3)元素是否为空值:

List 集合中允许存在多个空值

Set 最多允许一个空值出现

Map 中只允许出现一个空键,但允许出现多个空值

21.HashMap Hashtable 有什么区别?

1 HashMap 不是线程安全的 hastmap 是一个接口 是 map 接口的子接口,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。  HashMap 允许 null key null value 2 HashTable 是线程安全的一个 Collection

HashMap Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,主要区别在于 HashMap 允许空(null)键值(key,由于非线程安全,效率上可能高于 Hashtable。  HashMap 允许将 null 作为一个 entry  key 或者 value而 Hashtable 不允许。  HashMap Hashtable contains 方法去掉了,改成 containsvalue containsKey。因为 contains方法容易让人引起误解。   Hashtable 继承自 Dictionary 类,而 HashMap Java1.2 引进的 Map interface 的一个实现。  最大的不同是,  Hashtable 的方法是 Synchronize 的,而 HashMap 不是,在多个线程访问 Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 必须为之提供外同步。   Hashtable  HashMap 采用的hash/rehash 算法都大概一样,所以性能不会有很大的差异。

22.如何决定使用 HashMap 还是 TreeMap

TreeMap<K,V> Key 值是要求实现 java.lang.Comparable ,所以迭代的时候 TreeMap 认是按照 Key 值升序排序的;TreeMap 的实现是基于红黑树结构。适用于按自然顺序或自定义顺序遍历键(key)。

HashMap<K,V> Key 值实现散列 hashCode() ,分布是散列的、均匀的,不支持排序;数据结构主要是桶(数组),链表或红黑树。适用于在 Map 中插入、删除和定位元素。

23.说一下 HashMap 的实现原理?

HashMap 使用数组加链表实现。每个数组中储存着链表。当使用 put 方法储存 key-value 键值对时,会先调用 key hashCode 方法,得到此 key 经特定哈希运算后的值,然后将此值通过其他运算(?  得到一个值,将这个值与(length- 1)做或操作(&),相当于对数组长度做取余操作。最终得到一个值作为此 key 在数组中的索引值,然后将  key-value 键值对储存进去。

通过这种方法将储存的不同 key-value 键值对散列到数组的不同位置。

在储存的时候,如果索引位置尚无元素,那么直接储存。如果有元素,那么就调用此 key equals 方法与原有的元素的 Key

进行比较。如果返回 true,说明在这个 equals 定义的规则上,这两个 Key 相同,那么将原有的 key 保留,用新的 value 代替

原来的 value。如果返回 false,那么就说明这两个 key equals 定义的规则下是不同元素,那么就与此链表的下一个结点行比较,知道最后一个结点都没有相同元素,  再下一个是 null 的时候,就用头插法将此 key-value 添加到链表上。

HashMap 对重复元素的处理方法是:  key 不变,value 覆盖。

当使用 get 方法获取 key 对应的 value 时, 会和储存 key-value 时用同样的方法,得到 key 在数组中的索引值,  如果此索引值 上没有元素,就返回 null。如果此索引值上有元素,那么就拿此 key equals 方法与此位置元素上的 key 进行比较,如果返回 true。就返回此位置元素对应的 value。如果返回 false,就一直按链表往下比较,  如果都是返回 false,那么就返回 null

另外:  HashMap JDK1.8 之后引入红黑树结构。 HashMap 是线程不安全的,线程安全的是 CurrentHashMap,不过此集合在多线程下效率低。

24.说一下 HashSet 的实现原理?

首先,我们需要知道它是 Set 的一个实现,所以保证了当中没有重复的元素。 一方面 Set 中最重要的一个操作就是查找。而且通常我们会选择 HashSet 使用的是散列函数,那么它当中的元素也就无序可寻。当中是允许元素为 null 的。

25.ArrayList LinkedList 的区别是什么?

数据结构实现:   ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。    

 随机访问效率:  ArrayList  LinkedList 在随机访问的时候效率要高, 因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往  后依次查找。  

 增加和删除效率:   在非首尾的增加和删除操作,   LinkedList 要比 ArrayList 效率要高,    因为 ArrayList 增删操作 要影响数组内的其他数据的下标。   

综合来说:   在需要频繁读取集合中的元素时,   更推荐使用 ArrayList , 而在插入和删除操

作较多时,更推荐使用 LinkedList

26. 如何实现数组和 List 之间的转换?

List 转数组:  toArray()方法

数组转 ListArrays asList(a)方法

27.ArrayList Vector 的区别是什么?

这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合,即存储在这两个集合中的元素的位置都

是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,  并且其中的数据是允许重复的,这是与HashSet 之类的集合的最大不同处,  HashSet 之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素。

ArrayList Vector 的区别主要包括两个方面:  .

1)同步性:的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用 ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。

2)数据增长:

要增加 ArrayList Vector 的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增 加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。  Vector 默认增长为原来两倍,而 ArrayList 的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的 1.5 倍)  ArrayList Vector 都可以设置初始的空间大小,  Vector还可以设置增长的空间大小,而 ArrayList 没有提供设置增长空间的方法。

28.Array ArrayList 有何区别?

Array Java 中的数组,  声明数组有三种方式 int[] a=new int[10]; inta[]=new int[10]; int a[]={1,2,3,4}; 可以看出:在定义一个数组的时候,必须指定这个数组的数据类型及数组的大小,也就是说数组中存放的元素个数固定并且类型一样

ArrayList 是动态数组,也就是数组的复杂版本,它可以动态的添加和删除元素,被称为集合 ,集合的声明如下 ArrayList list= new ArrayList(10); ArrayList list1 = new ArrayList(); 可以看出:在不使用泛型的情况下,这个 list 是可以添加进不同类型的元素的,而且 arraylist 是可以不用指定长度的。在使用泛型时,我们就只能添加一种类型的数据了

29.Queue poll() remove()有什么区别?

相同点:都是返回第一个元素,并在队列中删除返回的对象。

poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。

30.哪些集合类是线程安全的?

Vector:就比 Arraylist 多了个同步化机制(线程安全)  。

Hashtable:就比 Hashmap 多了个线程安全。

ConcurrentHashMap:是一种高效但是线程安全的集合。

Stack:栈,也是线程安全的,继承于 Vector

31.迭代器 Iterator 是什么?

首先说一下迭代器模式,它是 Java 中常用的设计模式之一。用于顺序访问集合对象的元素,无需知道集合对象的底层实现。

Iterator 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦。

缺点是增加新的集合类需要对应增加新的迭代器类,迭代器类与集合类成对增加。

32.Iterator 怎么使用?有什么特点?

1 Iterator  ()要求容器返回一个 Iterator Iterator 将准备好返回序列的第一个元素。

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

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

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

有什么特点:

1 Iterator 遍历集合元素的过程中不允许线程对集合元素进行修改,否则会抛出

ConcurrentModifificationEception 的异常。

2 Iterator 遍历集合元素的过程中可以通过 remove 法来移除集合中

的元素,删除的是上一次 Iterator.next()方法返回的对象。

3 Iterator 必须依附于一个集合类对象而存在, Iterator 本身不具有装载数据对象的功能。

4 next  ()方法,该方法通过游标指向的形式返回 Iterator 下一个元

素。

33.Iterator ListIterator 有什么区别?

1)所属关系,  ListIterator 是一个 Iterator 的子类型。    

2)局限:只能应用于各种 List 类的访问。   

3)优势:Iterator 只能向前移动,而 ListIterator 可以双向移动。    

4 ListIterator add() 方法,可以向 List 中添加对象,而Iterator 不能。

34.怎么确保一个集合不能被修改?

我们可以采用 Collections 包下的 unmodifiableMap 方法,通过这个方法返回的 map,是不可以修改的。他会报java.lang.UnsupportedOperationException 错。

同理: Collections 包也提供了对 list set 集合的方法。    Collections.unmodififiableList(List)

Collections.unmodififiableSet(Set)

三、多线程

35.并行和并发有什么区别?

解释一:并行是指两个或者多个事件在同一时刻发生;  而并发是指两个或多个事件在同一时间间隔发生。

解释二:   并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。

解释三:在一台处理器上 同时处理多个任务,在多台处理器上同时处理多个任务。如 hadoop 分布式集群 所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

36.线程和进程的区别?

进程是执行着的应用程序,  而线程是进程内部的一个执行序列。  一个进程可以有多个线程。线程又叫轻量级进程。  线程的划分小于进程,线程是隶属于某个进程的。进程是程序的一种动态形式,是 CPU,内存等资源占用的基本单

位,而线程是不能占有这些资源的。

进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信比较方便。

进程在执行过程中包含比较固定的入口,执行顺序,出口,而线程的这些过程会被应用程序所控制。

37.守护线程是什么?

1、守护线程,专门用于服务其他的线程,如果其他的线程(即用户自定义线程)都执行完毕,连 main 线程也执行完

毕,那么 jvm 就会退出(即停止运行)  此时,连 jvm 都停止运行了,守护线程当然也就停止执行了。

2、再换一种说法,如果有用户自定义线程存在的话, jvm 就不会退出——此时,守护线程也不能退出,  也就是它还

要运行,干嘛呢,  就是为了执行垃圾回收的任务啊。

38.创建线程有哪几种方式?

1,继承 Thread 类,重写 run 方法;

2,实现 Runnable 接口,重写 run 方法,但是比继承 Thread 类好用,实现接口还 可以继承类,避免了单继承带来的局限性;

3,使用 Executor 框架创建线程池。  Executor 框架是 juc 里提供的线程池 的实现。   调用线程的 start():启动此线程;调用相

应的 run()方法

Thread 的常用方法:

1.start():启动线程并执行相应的 run()方法

2.run():子线程要执行的代码放入 run()方法中

3.currentThread():静态的,调取当前的线程

4.getName():获取此线程的名字

5.setName():设置此线程的名字

6.yield():调用此方法的线程释放当前 CPU 的执行权(很可能自己再次抢到资源)

7.join():A 线程中调用 B 线程的 join()

方法,表示:当执行到此方法, A 线程停止执行,直至 B 线程执行完毕,   A 线程再接着 join()之后的代码执行

8.isAlive():判断当前线程是否还存活

9.sleep(long l):显式的让当前线程睡眠 l 毫秒 (只能捕获异常,因为父类 run 方法没

有抛异常)

10.线程通信(方法在 Object 类中):  wait() notify() notifyAll() *设置线程的优先级(非绝对,只是相对几

率大些)

11.getPriority():返回线程优先值 setPriority(int newPriority):改变线程的优先级

39.说一下 runnable callable 有什么区别?

相同点:

1. 两者都是接口;(废话)

2. 两者都可用来编写多线程程序;

3. 两者都需要调用 Thread.start()启动线程

不同点:

1. 两者最大的不同点是:实现 Callable 接口的任务线程能返回执行结果;  而实现 Runnable 接口的任务线程不能返回结果;

2. Callable 接口的 call()方法允许抛出异常;而 Runnable 接口的 run()方法的异常只能在内部消化,不能继续上抛;

40.线程有哪些状态?

线程状态有 5 种, 新建,就绪,运行,阻塞,  死亡

新建状态:创建一个新的线程对象

就绪:新的线程对象调用 start()方法,该状态下的线程位于可运行的线程池中,等待获取 CPU 调度时间运行:线程池中的线程获取到了 CPU 的资源,开始执行程序

阻塞: 指运行状态下的线程因为某种原因放弃了 CPU 使用权,暂时停止运行,直到线程再次进入就绪状态才有机会获取 CPU 的资源进入到运行状态

(1)、等待阻塞:运行中的线程执行了 wait()方法,JVM 会把该线程放入等待队列(等待池)中

(2)、同步阻塞:运行中的线程在获取对象的同步锁时,若当前的对象锁被其他线程所占有,则 JVM 会将该线程放入锁池中

(3)、其他阻塞:运行中的线程执行了 Thread.sleep()方法   或者 join()方法,或者发送了 I/O 请求时,JVM 会将该线程设置为阻塞状态

死亡:线程 run(),main()方法执行结束,或值 run()执行过程中出现异常,则该线程结束生命周期

1. 线程 start 方法执行后,并不表示该线程运行了,而是进入就绪状态,意思是随时准备运行,但是真正何时运行,是由操作系统决定的,  代码并不能控制,

2. 同样的,从运行状态的线程,也可能由于失去了 CPU 资源,回到就绪状态,也是由操作系统决定的。这一步中,也可以由程序主动失去 CPU 资源,只需调用 yield 方法。

3. 线程运行完毕,或者运行了一半异常了,或者主动调用线程的 stop 方法,那么就进入死亡。死亡的线程不可逆转。

4. 下面几个行为,会引起线程阻塞。

主动调用 sleep 方法。时间到了会进入就绪状态 主动调用 suspend 方法。主动调用 resume 方法,会进入就绪状态调用了阻塞式 IO 方法。调用完成后,会进入就绪状态。   试图获取锁。成功的获取锁之后,会进入就绪状态。   线程在等待某个通知。其它线程发出通知后,会进入就绪状态

41.sleep() wait() 有什么区别?

1、同步锁 zd 的对待不同:

sleep()后,程序并不会不释放同步锁。

wait  ()后,程序会释放同步锁。

2、用法的不同:

sleep()可以用时间指定版来使他自动醒过来。如果时间不到你只能调用 interreput()来强行打断。

wait  ()可以用 notify()直接唤起。

(1)sleep()方法是 Thread 类中的静态方法,wait 属于 Object 基类的成员方法(他们都会是线程进入到阻塞状态)

(2)sleep()方法是线程类(Thread)的方法,不会涉及到线程通信,调用 sleep()方法后会使线程睡眠指定的时间,但此时线程不会释 放同步锁。  wait()涉及到线程通信问题,在调用 wait 方法后线程会主动释放同步锁.进入等待队列,可以通过 notify/notifyAll

唤醒线程。才会进入锁池中准备获取对象锁

(3)对象的 wait 方法即 notify()、 notifyAll()只能在同步代码块中执行,  sleep()能随处调用

(4)sleep()方法必须捕获异常(InterruptedException), wait 方法即 notify() notifyAll()则不需要

42.notify()notifyAll()有什么区别?

锁池:假设线程 A 已经拥有了某个对象(注意:不是类)的锁, 而其它的线程想要调用这个对象的某个 synchronized 方法   (或者 synchronized ),由于这些线程在进入对象的 synchronized 方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程 A 拥有,所以这些线程就进入了该对象的锁池中。

等待池:假设一个线程 A 调用了某个对象的 wait()方法,线程 A 就会释放该对象的锁后,进入到了该对象的等待池中

如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,  等待池中的线程不会去竞争该对象的锁。

当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒    的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,  调用了 notify 后只要一个线程会由  等待池进入锁池,而 notifyAll 会将该对象等待池内的所有线程移动到锁池中,等待锁竞争 优先级高的线程竞争到对象 锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()法,它才会重新回到

等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

43.线程的 run()start()有什么区别?

调用 start() 方法是用来启动线程的,轮到该线程执行时,会自动调用 run();直接调用 run() 方法,无法达到启动多线程的目的,相当于主线程线性执行 Thread 对象的 run() 方法。   一个线程对线的 start() 方法只能调用一次,多次调用会抛出 java.lang.IllegalThreadStateException 异常;  run() 方法没有限制。

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

1 newCachedThreadPool(),它是用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置时间超过 60 秒,则被终止并移除缓存;长时间闲置时,这种线程池,  不会消耗什么资源。其内部使用 SynchronousQueue 为工作队列。

2 newFixedThreadPoolint nThreads),重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。这意味着,如果任务数量超过了活动线程数目,将在工作队列中等待空闲线程出现;如果工作线程退出,将会有新的工作线程被创建,  以补足指定数目 nThreads

3 newSingleThreadExecutor(),它的特点在于工作线程数目限制为 1,操作一个无界的工作队列,所以它保证了所   有的任务都是被顺序执行,  最多会有一个任务处于活动状态,并且不予许使用者改动线程池实例,因此可以避免改变线程数目。

4 newSingleThreadScheduledExecutor()newScheduledThreadPool(int corePoolSize),创建的是个ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。

5 newWorkStealingPool(int parallelism),这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建 ForkJoinPool,利用 Work-Stealing 算法,并行地处理任务,不保证处理顺序。

45.线程池都有哪些状态?

1. RUNNING:线程池一旦被创建,就处于 RUNNING 状态,任务数为 0,能够接收新任务,对已排队的任务进行处理。

2. SHUTDOWN:不接收新任务,但能处理已排队的任务。调用线程池的 shutdown() 方法,线程池由 RUNNING 变为 SHUTDOWN 状态。

3. STOP:不接收新任务,  不处理已排队的任务,并且会中断正在处理的任务。调用线程池的 shutdownNow() 法,线程池由(RUNNING SHUTDOWN ) 转变为 STOP 状态。

4. TIDYING

SHUTDOWN 状态下,任务数为 0 , 其他所有任务已终止,线程池会变为 TIDYING 状态,会执行 terminated() 法。线程池中的 terminated() 方法是空实现,可以重写该方法进行相应的处理。线程池在 SHUTDOWN 状态,任务队列为空且执行中任务为空,线程池就会由 SHUTDOWN 转变为 TIDYING 状态。线程池在 STOP 状态,线程池中执行中任务为空时,就会由STOP TIDYING 状态。

5. TERMINATED:线程池彻底终止。线程池在 TIDYING 状态执行完 terminated() 方法就会由 TIDYING 转变为TERMINATED 状态。

46.线程池中 submit()execute()方法有什么区别?

submit(Callable task)submit(Runnable task, T result)submit(Runnable task)归属ExecutorService 接口。execute(Runnable command)归属于 Executor 接口。 ExecutorService 继承了 Executor

47. java 程序中怎么保证多线程的运行安全?

线程的安全性问题体现在:

原子性:  一个或者多个操作在 CPU 执行的过程中不被中断的特性 可见性: 一个线程对共享变量的修改,另外一个线程能够立刻看到 有序性:  程序执行的顺序按照代码的先后顺序执行

导致原因:

缓存导致的可见性问题 线程切换带来的原子性问题 编译优化带来的有序性问题解决办法:

JDK Atomic 开头的原子类、  synchronized LOCK,可以解决原子性问synchronizedvolatile LOCK,可以解决可见性问题 Happens-Before 规则可以解决有序性问题

48.多线程锁的升级原理是什么?

锁的级别从低到高:

无锁 - > 偏向锁 - > 轻量级锁 - > 重量级锁

锁分级别原因:

没有优化以前,  synchronized 是重量级锁(悲观锁),使用 wait notify notifyAll 来切换线程状态非常消耗系统  资源;线程的挂起和唤醒间隔很短暂,这样很浪费资源,影响性能。所以 JVM synchronized 关键字进行了优化,把锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。

无锁:没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功,其他修改失败的线程会不断重试直到修改成功。

偏向锁:对象的代码一直被同一线程执行,不存在多个线程竞争,该线程在后续的执行中自动获取锁,降低获取锁带 来的性能开销。偏向锁,指的就是偏向第一个加锁线程,该线程是不会主动释放偏向锁的,只有当其他线程尝试竞争偏向锁才会被释放。偏向锁的撤销,需要在某个时间点上没有字节码正在执行时,先暂停拥有偏向锁的线程,然后判断锁对象是否处于被锁定状态。如果线程不处于活动状态,则将对象头设置成无锁状态,并撤销偏向锁;如果线程处于活动状态,升级为轻量级锁的状态。

轻量级锁:轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级锁;当一个线程已持有锁,  另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。

重量级锁:指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock 现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。

49.什么是死锁?

死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力 作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 

50.怎么防止死锁?

尽量使用 tryLock(longtimeout, TimeUnit unit)的方(ReentrantLock ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。 尽量使用 Java. util. concurrent 并发类代替自己手写锁。 尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。 尽量减少同步的代码块。

51.ThreadLocal 是什么?有哪些使用场景?

Thread Local 类是线程局部变量,是一种实现线程安全的方式。但是在管理环境下使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,  Java 应用就存在泄露大的风险

52.说一下 synchronized 底层实现原理?

可以保证方法或代码块在运行时,同一时刻只有一个方法可以进入临时界区,同时它还可以保证共享变量的内存可见

普通同步方法,锁是当前实列对象

静态同步方法,锁是当前类的 class 对象

同步方法块,锁是括号里面的 对象

53.synchronized volatile 的区别是什么?

volatile 本质是告诉 jvm 当前变量寄存器中的值是不确定的,需要从主存中读取; synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞。

volatile 仅能实现变量的修改可见性,不能保证原子性;  而 synchronized 则可以保证变量的修改和可见性

volatile 不会造成线程阻塞;  synchronized 可能会造成线程阻塞。

volatile 标记的变量不会被编译器优化;  synchronized 可能被编译器优化

54.synchronized Lock 有什么区别?

首先 synchronized Java 内置关键字,在 jvm 层里面,  LOck 是个类;

synchronized 无法判断是否获取锁的状态,  lock 可以判断是否获取到锁

synchronized 会自动释放锁,否则容易造成线程死锁

synchronized 会等待线程,  Lock 锁不会等待如果尝试获取不到锁,线程可以不用一直等待就结束了

synchronized 锁适合代码少量的同步问题,  lock 锁适合大量的代码同步问题

55.synchronized ReentrantLock 区别是什么?

一个是关键字,  一个是类,  更灵活的特性,可被继承可以有方法

ReentrantLock 可以获取锁的等待时间设置,这样避免死锁,各种锁的信息,灵活实现多路通知

56.说一下 atomic 的原理?

当多个线程同时对该变量进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,  一直等待到执行成功

四、反射

57.什么是反射?

主要指程序可以访问,检测,修改本生状态或行为的一种能力

Java 运行是环境中,对任意一个类,是否知道这个类有属性和方法?

58.什么是 java 序列化?什么情况下需要序列化?

序列化:将 Java 对象转换成字节流的过程。

反序列化:将字节流转换成 Java 对象的过程。当 Java 对象需要在网络上传输 或者 持久化存储文件中时,就需要对 Java 象进行序列化处理。

序列化的实现:类实现 Serializable 接口,  这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉jvm 这个类的对象可以被序列化。

59.动态代理是什么? 有哪些应用?

当想要给实现某个接口的类中的方法,加一些格外的处理。比如加日志,  加事务,  加权限等。可以给这个类创建一个代理,这个代理并不是定义好的,是动态生成的,具有解耦,灵活,扩展性强

60.怎么实现动态代理?

首先必须定义一个接口,还要有一个 InvocationHandler 处理类,再有一个工具类 Proxy。利用到 InvocationHandler处理类,拼接代理类源码,  将其编译生成代理类的二进制码,利用加载器加载,并将其实列化产生代理对象,  最后返

五、对象拷贝

61.为什么要使用克隆?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。克隆分浅克隆和深克隆,浅克隆后的对象中非基本对象和原对象指向同一块内存,因此对这些非基本对象的修改会同时更改克隆前后的对象。深克隆可以实现完全的克隆,可以用反射的方式或序列化的方式实现。

62.如何实现对象克隆?

1 实现 Cloneable 接口并重写 object 类中的 clone  ()方法

2 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

63.深拷贝和浅拷贝区别是什么?

浅拷贝只是复制了对象的引用地址,两个对象指向同一内存地址,所有修复其中的任意值,另一个值都会随之变化深拷贝是将对象及值复制过来,两个对象修改其中任意值另一个值不会改变

六、 Java Web

64.jsp servlet 有什么区别?

jsp 编译后变成了 servlet

jsp 更擅长变现页面显示,  servlet 更擅长逻辑控制

servlet 没有内置对象,  jsp 的内置对象都是必须通过 httpservletrequst 对象,  httpservletrespose 对象以及

httpservlet 对象得到的

jsp servlet 的一种简化

65.jsp 有哪些内置对象?作用分别是什么?

request:封装客户请求 get post

response:封装服务器对客户端的响应

pageContext:通过对该对象获取其他对象

session:封装用户会话的对象

application:封装服务器运行环境的对象 out:输出服务器响应的输出流对象

confifigweb 应用的配置对象

pagejsp 页面本身

exception:封装页面抛出异常的对象

66.说一下 jsp 4 种作用域?

page:jsp 页面本身

request:封装客户请求 get post

response:封装服务器对客户端的响应

application:封装服务器运行环境的对象

67.session cookie 有什么区别?

由于 HTTP 协议是无状态的协议,所以服务端余姚记录用户的状态 session 是保存在服务端的

cookie 是保存在客户端的

68.说一下 session 的工作原理?

session 是一个存在服务器上的类似于一个散列表格的文件,里面存有我们需要信息,需要用的时候取出来,类似于大号的 map,里面的键存储的是用户的 sessionid,用户向服务器发送请求的时候会带上这个 sessionid。就可以从中取值

69.如果客户端禁止 cookie 能实session 还能用吗?

不能的到 session,禁用相当于失去 session ,一般认为两个是独立的东西,  cookie 采用的是客户端保持状态方案,session 采用的是客户端保持方案

70.spring mvc struts 的区别是什么?

struts2 是类级别的拦截器,  struts2 Action 的一个方法可以对应一个 url,而其类属性却被所有方法共享,这也就无法用注解或其他的方式标识其所属方法了,只能设计为多例

springmvc 是方法级别的拦截,在 spring 整合时,  springmvc controller Bean 默认单列模式 Singleton,所以默认对所有的请求,只会创建一个 controller

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值