Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 327|回复: 5

Java面试知识点

[复制链接]

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
发表于 2019-4-12 08:12:22 | 显示全部楼层 |阅读模式
本帖最后由 java 于 2019-5-7 11:29 编辑

什么是Java内存模型?

多线程同步和互斥有哪几种实现方法?
线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。
内核模式下的方法有:事件,信号量,互斥量。
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。
3、信号量:为控制一个具有有限数量用户资源而设计。
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。

悲观锁和乐观锁有什么区别?
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

Java的锁实现机制,使用场景分析

ReentranLock源码,设计原理,整体过程

volatile的实现原理

AQS的实现过程



应聘高级Java开发工程师:

1. 如何保证系统高可用
通过冗余+自动故障转移来实现系统的高可用,两套nginx,Tomcat,redis主从服务器+哨兵
https://linux.cn/article-8377-1.html
http://gitbook.cn/books/583c1335c7f2666319396f7f/index.html
http://dbaplus.cn/news-141-591-1.html

2. 系统容灾设计
http://blog.51cto.com/zhaisj/40986

3. 保证分布式系统数据一致性
https://mp.weixin.qq.com/s?__biz ... 0c21bd3e5d&scene=21

4. Java内存管理
http://blog.csdn.net/suifeng3051/article/details/48292193

5. JDK常用类库源码
http://blog.csdn.net/u011915230/article/details/53243515
http://blog.csdn.net/tanggao1314/article/details/50989589
http://770736680.iteye.com/blog/2034936
http://blog.csdn.net/jjzhu_zju/article/details/53674497

6. HashMap原理及数据存储过程
https://yikun.github.io/2015/04/ ... %E5%AE%9E%E7%8E%B0/

7. Java并发控制工具
http://blog.csdn.net/coderinchina/article/details/54914852
http://blog.csdn.net/zq602316498/article/details/41779431
http://softbeta.iteye.com/blog/1797163
http://blog.csdn.net/axi295309066/article/details/52914867

8. SQL查询慢的原因
http://blog.csdn.net/lzkqcc/article/details/79099942

9. spring启动容器加载初始化过程
http://www.cnblogs.com/luyanliang/p/5567164.html
http://blog.csdn.net/u013510838/article/details/75066884
http://www.cnblogs.com/ViviChan/p/4981712.html

10.项目设计的时候关注哪些方面或者系统设计需要考虑哪些方面
http://vividfree.github.io/%E4%B ... about-system-design
---------------------
原文:https://blog.csdn.net/dutianqi110/article/details/79501031


JAVA8 十大新特性详解
回复

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
 楼主| 发表于 2019-4-19 19:17:00 | 显示全部楼层
本帖最后由 java 于 2019-4-19 19:21 编辑

ArrayList、Vector和LinkedList

首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList、Vector和LinkedList。List用于存放多个元素,能够维护元素的次序,并且允许元素的重复。3个具体实现类的相关区别如下:
  • ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
  • Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
  • LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。
  • vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
  • 如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度
    的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。
  • 如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而
    如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用Linkedlist,因为它移动一个指定位置的数据
    所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。
    ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,
    都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,
    Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差
    ,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!
  • 笼统来说:LinkedList:增删改快
                  ArrayList:查询快(有索引的存在)



线程安全
数组和链表
空间增长率
访问读写速度


回复 支持 反对

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
 楼主| 发表于 2019-4-19 19:45:47 | 显示全部楼层
本帖最后由 java 于 2019-4-19 19:47 编辑

Spring注解
  • @Repository、@Component、@Service、@Constroller,都是将一个类标识为Bean,Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IoC容器中,它们分别用于软件系统的不同层次:
  • @Repository 将 DAO 类声明为 Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。
  • @Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次。
  • @Service通常作用在业务层,但是目前该功能与 @Component 相同。
  • @Constroller 通常作用在控制层,但是目前该功能与 @Component 相同。
    -@Autowired进行装配,默认是byType的方式进行自动装配的。

SpringBoot注解
  • @RestController 在源码声明上同时有 @Controller 和 @ResponseBody 注解,所以使用了这个注解的类会被看作一个Controller,所以 @RestController 与 @Controller 的区别就是,@Controller返回的是ViewAndModel,@RestController返回的是字符串直接发送回给客户端。

  • @EnableAutoConfiguration 注解是类级别的,这个注解告诉Spring Boot“猜测”将如何配置Spring,它是基于添加的jar依赖。

链接:https://www.jianshu.com/p/13de8e13173c






回复 支持 反对

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
 楼主| 发表于 2019-4-19 20:51:55 | 显示全部楼层
Filter是Spring过滤器,要定义一个Filter类有以下步骤:
首先定义一个Filter类,继承javax.servlet.Filter类,重写其init、doFilter、destroy方法。init()方法会在Filter初始化后进行调用,在init()方法里面我们可以通过FilterConfig访问到初始化参数( getInitParameter()或getInitParameters() )、ServletContext (getServletContext)和当前Filter部署的名称( getFilterName() )等信息。destroy()方法将在Filter被销毁之前调用。而doFilter()方法则是真正进行过滤处理的方法,在doFilter()方法内部,我们可以过滤请求的request和返回的response,同时我们还可以利用FilterChain把当前的request和response传递给下一个过滤器或Servlet进行处理。

同时配置过滤器和拦截器然后请求,结果如下:
init yes
filter test
interceptortest pre
controller
interceptortest post
interceptortest after
可以看到filter优先于interceptor被调用。
过滤器和拦截器主要区别如下:
1.二者适用范围不同。Filter是Servlet规范规定的,只能用于Web程序中,而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。
2.规范不同。Filter是在Servlet规范定义的,是Servlet容器支持的,而拦截器是在Spring容器内的,是Spring框架支持的。
3.使用的资源不同。同其他代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象(各种bean),而Filter不行。
4.深度不同。Filter只在Servlet前后起作用,而拦截器能够深入到方法前后、异常跑出前后等,拦截器的使用有更大的弹性。

回复 支持 反对

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
 楼主| 发表于 2019-4-26 11:18:46 | 显示全部楼层
volatile关键字保证不了线程安全
想要线程安全必须保证原子性,可见性,有序性。而volatile只能保证可见性和有序性
总线锁
    缓存一致性协议
我写入之后发现这是共享变量就使得其他cpu缓存了的值失效,让它再次去内存中读取。
这样如果有一个变量i = 0用volatile修饰,两个线程对其进行i++操作,如果线程1从内存中读取i=0进了缓存,然后把数据读入寄存器,之后时间片用完了,然后线程2也从内存中读取i进缓存,因为线程1还未执行写操作,内存屏障是插入在写操作之后的指令,意味着还未触发这个指令,所以缓存行是不会失效的。然后线程2执行完毕,内存中i=1,然后线程1又开始执行,然后将数据写回缓存再写回内存,结果还是1。
https://blog.csdn.net/qq_33330687/article/details/80990729

回复 支持 反对

使用道具 举报

697

主题

1142

帖子

4086

积分

认证用户组

Rank: 5Rank: 5

积分
4086
 楼主| 发表于 2019-4-27 09:30:15 | 显示全部楼层
本帖最后由 java 于 2019-4-27 16:52 编辑

String s=new String("xyz");创建了几个String Object?二者之前的区别是什么?

      两个。第一个对象是字符串常量"xyz" 第二个对象是new String("xyz")的时候产生的,在堆中分配内存给这个对象,只不过这个对象的内容是指向字符串常量"xyz" 另外还有一个引用s,指向第二个对象。这是一个变量,在栈中分配内存。

-----------

   //检查型异常(Checked Exception)   FileNotFoundException

//非检查型异常(Unchecked Exception)数组越界、访问null对象,这种错误你自己是可以避免的。编译器不会强制你检查这种异常。

-----------------

存在i+1<i的数
-------------
二分查找要求结点 ___A___。

A.有序,顺序存储
B.有序,链接存储
C.无序,顺序存储
D.无序,链接存储
[解析] 二分查找要求结点有序且顺序存储。因为查找时,是根据中间元素的位置来确定应该是在左边查找,还是在右边查找。
-------------

如果你想列出当前目录以及子目录下所有扩展名为“.txt”的文件,那么你可以使用的命令是
  • find . -name "*.txt"
---------------


String是线程安全的
因为String是不可改变的,所以是线程安全的,改不了。
String 字符串常量(产生新变量 线程安全)
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
-----------------

垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
1对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。
       通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。
     2、可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

----------------------------

Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用==还是equals()?它们有什么区别?
      Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判断两个Set是否相等。
      ==比较两个变量本身的值,即两个对象在内存中的首地址是否相同。
      equals()主要是比较对象中包含的值是否相同。
1、什么是Set?(what)
     Set是Collection容器的一个子接口,它不允许出现重复元素,当然也只允许有一个null对象。
2、如何来区分重复与否呢?(how)
     “ 用 iterator() 方法来区分重复与否 ”,这是在网上流传的答案,个人认为这是个错误的答案。JPI中写的很明白:“set 不包含满足
e1.equals(e2) 的元素对 e1 和 e2 ”,由此可见回答使用equals()区分更合适。
3、为什么用equals()而不用==来区分?(why)
     应该从它俩的区别谈起,==是用来判断两者是否是同一对象(同一事物),而equals是用来判断是否引用同一个对象。再看一下Set里面存的是
对象,还是对象的引用。根据java的存储机制可知,set里面存放的是对象的引用,所以当两个元素只要满足了equals()时就已经指向同一个对象,
也就出现了重复元素。所以应该用equals()来判断。

-------------------
Servlet执行时一般实现哪几个方法?

  答:

  public void init(ServletConfig config)
  public ServletConfig getServletConfig()
  public String getServletInfo()
  public void service(ServletRequest request,ServletResponse response)
  public void destroy()

-----------------------
try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,还是在return之后执行?
https://www.cnblogs.com/hongten/ ... n_java_finally.html
上图是当程序执行完finally模块后,返回到return代码块。

但是在最后的运行效果中,我们看到的结果是:1,而不是我们想象中的:2

为什么会出现这样的情况:
finally.png

总结
这一个面试题,看似简单,却暗藏杀机啊!
可是说了这么多,结果就是finally在return之后执行吗?
非也,你没看见return没有真正的执行完就开始执行finally吗?并且是先执行完了finally,才执行完return,这也就很好理解java规范中的finally在return之前执行了。

不过,按如上情况,这句话应该变成这样:finally比return先执行完毕。是不是就更容易理解了呢?
也就是说,return先被执行了,执行return的时候发现有finally,于是不能那么快执行完毕return,先去执行finally,等finally执行完毕之后,return才能执行完毕。

-------------
abstract class和interface有什么区别
含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

下面比较一下两者的语法区别:

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5. 抽象类中可以包含静态方法,接口中不能包含静态方法

6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

7. 一个类可以实现多个接口,但只能继承一个抽象类。
------------

怎么获取 Java 程序使用的内存?堆使用的百分比?
1、可以使用JMAP或者JStat工具查看Java内存的详细使用情况
2、也可以使用VisualGC查看内存使用情况。可视化工具。
------------

什么是线程局部变量?做例子测试threadlocal
----------------
简述synchronized和java.util.concurrent.locks.Lock的异同?
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。





回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2021-4-12 14:39 , Processed in 1.158494 second(s), 22 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表