2016年换了新工作,这期间到各大公司进行面试,面试前在网上搜索了最新的java面试宝典以及java笔试题100道等等,面试过程中信心满满,在做完几家企业的java笔试题以及回答面试官面试题后,发现之前的面试准备虽然费了洪荒之力,但是面试结果竟不尽人意。在亲身经历几次挫折后终于成功获得心仪单位的offer,我的之前亲身经历,真的是血淋淋的前车之鉴啊!一套2016年最新版java面试考点将助你不费洪荒之力搞定java面试,现良心整理之作,供后来者参考,把如下考点搞清楚通过笔试面试应该问题不大。现呈上干货如下,共勉!
今年考点集中在:线程、并发、以及流行框架的源码和架构这几个方面。
1)什么是进程?
进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。
2)什么是线程?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。
3)java有三种方式可以用来创建线程
- java不支持类的多重继承,但允许你调用多个接口
1.继承Thread类 最简单的 new 方法,继承一个线程类
2.实现Runnable接口 当需要继承其他类的功能时,选runnable接口
3.借助框架程序 可用Executor框架来创建线程池,线程池可以限制线程的数量并且可以回收再利用这些线程
4)概括解释线程在执行过程中存在如下几种状态,注意了解其之间的区别。
- 就绪(Runnable):线程准备运行,不一定立马就能开始执行。
- 运行中(Running):进程正在执行线程的代码。
- 等待中(Waiting): 线程处于阻塞的状态,等待外部的处理结束。
- 睡眠中(Sleeping):线程被强制睡眠。
- I/O阻塞(Blocked on I/O):等待I/O操作完成。
- 同步阻塞(Blocked on Synchronization):等待获取锁。
- 死亡(Dead):线程完成了执行。
5)如何创建守护线程?
使用Thread类的setDaemon(true)方法可以将线程设置为守护线程,需要注意的是,需要在调用start()方法前调用这个方法,否则会抛出IllegalThreadStateException异常。
6)用户线程和守护线程(Daemon线程)有什么区别?
当我们在Java程序中创建一个线程,它就被称为用户线程。一个守护线程是在后台执行并且不会阻止JVM终止的线程。当没有用户线程在运行的时候,JVM关闭程序并且退出。一个守护线程创建的子线程依然是守护线程。
守护进程能被jvm终止退出,用户进程不能被jvm终止。
daemon线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。
7)如何确保线程安全?
在Java中可以有很多方法来保证线程安全——同步,使用原子类(atomic concurrent classes),实现并发锁,使用volatile关键字,使用不变类和线程安全类。
同步synchronized
同步块大家都比较熟悉,通过 synchronized 关键字来实现;所有加上 synchronized 的方法和块语句,在多线程访问的时候,同一时刻只能有一个线程能够访问。
volatile 关键字
volatile 是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile 变量可以保证下一个读取操作会在前一个写操作之后发生。线程都会直接从内存中读取该变量并且不缓存它。这就确保了线程读取到的变量是同内存中是一致的。
ThreadLocal 变量
ThreadLocal 是Java里一种特殊的变量。每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了。如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。
8) 线程sleep 和wait 的区别
sleep指线程进入休眠状态,保持对象锁,仅释放cpu。
wait指线程处于进入等待状态,释放对象锁,释放cpu。
sleep(100L)意思为:保持对象锁,线程休眠100毫秒
wait(100L)意思为:释放对象锁,线程等待100毫秒。
不同在于sleep方法是Thread类中的方法,调用它的时候不会释放锁;wait方法是Object类中的方法,调用它的时候会释放锁。
Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁。需要注意的是,sleep()并不会让线程终止,一旦从休眠中唤醒线程,线程的状态将会被改变为Runnable,并且根据线程调度,它将得到执行。
9) Thread 类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新创建的线程,使该被创建的线程状态变为可运行状态。
当你调用run()方法的时候,没有新的线程启动,只会是在原来的线程中调用,这个方法同普通类的run方法一样。
- Java中Runnable和Callable有什么不同?
Runnable:JDK1.0开始就有了,仅是执行Runnable的run()方法没有返回结果。
Callable是在JDK1.5增加的。不仅执行,Callable的 call() 方法可以返回值和抛出异常,且还可以返回装载有计算结果的Future对象。
11) 死锁
多线程,竞争资源,非法进程推进程序,(循环等待)。
处理策略 :鸵鸟策略,预防策略,避免策略,检测和恢复策略
-
int、integer的区别
1)int是基本数据类型,integer是int的封装类(引用类型) -
作为类的成员变量初始值不同,一个为0,一个为null。
3)直接赋值的时候,在【-128-127】范围内int=10和integer=10是一样的。
4)有new integer值的时候,对象里存的是引用地址,故不能用==直接比较,而应该封装类的方法equals来判断。
整型数据类型长度:byte(8bits)、short(16bits)、int(32bits)、long(64bits),与平台无关。 -
String类和StringBuffer类的区别
stringbuffer区别于string的地方在于:多用于处理动态的字符,对字符进行增加或删除。
StringBuilder:线程非安全的,速度快,适用于单线程
StringBuffer: 线程安全的,速度慢,适用于多线程
14)、&和&&的区别?
&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。
15)抽象类和接口的区别
抽象类是对类的抽象,是可以拥有自己的成员变量和具体方法实现的类;而接口是对行为的抽象,没有具体的实现方法,主要视为了实现多继承。
16)java的内存管理(jvm优化)
【堆、栈、方法区、程序计算器】
image_thumb_1.png java.jpg 无标题.jpg
jvm将内存分为:堆内存、栈内存
或者:新生代(young generations)、老年代(older generations)、永久代
堆内存: 年轻代和年老代。
新生代就是存放新建的对象,如果gc没有回收的对象就会进入老年代。
17)gc垃圾回收
意义:jvm的系统线程自动执行垃圾回收gc,既可以释放没用的对象,也可以清除内存记录碎片。
垃圾回收算法:(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。
垃圾回收算法可以分为三类,都基于标记-清除(复制)算法:Serial算法(单线程)、并行算法、并发算法。
程序员可以通过** System.gc()方法去提交清理垃圾的请求,由jvm自己来确定是否进行回收。
** 减少GC开销
(1)不要显式调用System.gc()
(2)尽量减少临时对象的使用
(3)尽量使用StringBuffer,而不用String来累加字符串
(4)尽量少用静态对象变量
- 内存泄漏(memory leak)和内存溢出(out of memory)的区别
-
内存溢出:指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
jvm 何时抛出OutOfMemoryException:并不是内存被耗空的时候才抛出
1)JVM98%的时间都花费在内存回收
2)每次回收的内存小于2% -
内存泄露:指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
或【内存中存在可达、无用的对象,且不会被GC回收,一直占用着内存。
该对象就是内存泄漏的对象 】 -
泄漏强调无法收回,占用内存;溢出强调不够,无法满足。
- 内存溢出常见解决办法
第1种 OutOfMemoryError: PermGen space
永久性存在的Permanent Generation space不够了。
JAVA_OPTS=" -XX:PermSize=64M -XX:MaxPermSize=128m"
可以通过 增加java虚拟机中的参数大小。
第2种 OutOfMemoryError:Java heap space
检查程序是否有冗余的对象,调整参数,增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。set JAVA_OPTS= -Xms256m -Xmx1024m。
20) 如何监控tomcat的内存情况
tomcat是通过java跑起来的,查看对应的pid之后,可以通过jvm自带的监控工具
jstat和jconsole来进行查看内存中的堆内存的和非堆内存的内容。
21)如何实现一个servlet?
- 实现Servlet接口* 继承GenericServlet类* 继承HttpServlet类
创建一个自定义的servlet类,实现java中servlet接口,该接口包含5个方法。
或者继承 GenericServlet类 或者 继承HttpServlet类。
- Servlet生命周期?
分为三个阶段:
1,初始化阶段 调用init()方法
2,响应客户请求阶段 调用service()方法
3,终止阶段 调用destroy()方法
23)MVC的各个部分都有那些技术来实现?如何实现?
MVC是三个单词的缩写,分别为:模型(Model),视图(View)和控制Controller)。 MVC模式的目的就是实现Web系统的职能分工。 Model层实现系统中的业务逻辑,通常可以用JavaBean或EJB来实现。 View层用于与用户的交互,通常用JSP来实现,freemarker velocity。 Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作,通常可以用Servlet来实现。
24) java并发
并发的一个重要原因是提高执行效率
为了实现并发,操作系统层面提供了多进程。
还有一种比较轻量的并发实现是使用线程,一个进程可以包含多个线程。 Java 语言中支持多线程。
25)线程协作
线程的通信:下面3个方法只能在同步块里面被调用
wait() 使线程进入睡眠状态
notify() 随机唤醒一个等待的线程,它将获得一次抢夺锁的机会notifyAll() 唤醒所有等待的线程
26)死锁【死锁有四个必要条件,打破一个即可去除死锁】
四个必要条件:
互斥条件。 一个资源每次只能被一个进程使用。
请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:线程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。
友情提示
我是和奇谷朴,一个上班族,读完我的文章如果今年面试通过了,记得打赏、关注和点赞哦!么么哒!!
网友评论
https://www.jianshu.com/p/e2d53c2109b0
这个建议是错的,Stringbuffer的所有字符串操作都是同步的,比StringBuilder的开销要大,绝大部分场景都应该用Stringbuilder去拼接字符串,更何况即使你用加号拼接字符串新版本的编译器会用自动用Stringbuilder去代替。