javaEE面试宝典
Posted IT技术大神
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javaEE面试宝典相关的知识,希望对你有一定的参考价值。
1.1 Collection和Map
(1)掌握Collection和Map的继承体系。
1.2 IO流
掌握InputStream、OutputStream、Reader、Writer的继承体系。
IO流中的设计模式
1.IO中用到的适配器模式
在IO中,如将字符串数据转变成字节数据保存到文件中,将字节数据转变成流数据等都用到了适配器模式,下面以InputStreamReader和OutputStreamWriter类为例介绍适配器模式。
InputStreamReader和OutputStreamWriter类分别继承了Reader和Writer接口,但要创建它们必须在构造函数中传入一个InputStream和OutputStream的实例,InputStreamReader和OutputStreamWriter的作用也就是将InputStream和OutputStream适配到Reader和Writer。
InputStreamReader实现了Reader接口,并且持有了InputStream的引用,这是通过StreamDecoder类间接持有的,因为byte到char要经过编码。
这里,适配器就是InputStreamReader类,而源角色就是InputStream代表的实例对象,目标接口就是Reader类,OutputStreamWriter类也是类似的方式。
在IO中类似的还有,如StringReader将一个String类适配到Reader接口,ByteArrayInputStream适配器将byte数组适配到InputStream流处理接口。
2.IO中用到的装饰模式
装饰模式就是对一个类进行装饰,增强其方法行为,在装饰模式中,作为原来的这个类使用者还不应该感受到装饰前与装饰后有什么不同,否则就破坏了原有类的结构了,所以装饰器模式要做到对被装饰类的使用者透明,这是对装饰器模式的一个要求。总之装饰器设计模式就是对于原有功能的扩展
在IO中有许多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的,
下面以FilterInputStream为例介绍装饰器模式的使用。
InputStream类就是以抽象组件存在的, 而FileInputStream就是具体组件,它实现了抽象组件的所有接口,FilterInputStream类就是装饰角色,它实现了InputStream类的所有接口,并持有InputStream的对象实例的引用,BufferedInputStream是具体的装饰器实现者,这个装饰器类的作用就是使得InputStream读取的数据保存在内存中,而提高读取的性能。类似的还有LineNumberInputStream类,它的作用是提高按行读取数据的功能。
总结
这两种设计模式看起来都是起到包装一个类或对象的作用,但是使用它 们的目的却不尽相同。适配器模式主要在于将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的;而装饰器模式不是要改变被装饰对象的接口,而是保持原有的接口,但是增强原有对象的功能,或改变原有对象的方法而提高性能。
补充☆(3) 高性能的IO体系。
首先得明白什么是同步,异步,阻塞,非阻塞.
1,同步和异步是针对应用程序和内核的交互而言的
2,阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式
总结一句简短的话,同步和异步是目的,阻塞和非阻塞是实现方式。
名词解释
同步阻塞IO(JAVA BIO):
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
同步非阻塞IO(Java NIO) : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。用户进程也需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问。
异步阻塞IO(Java NIO):
此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄(如果从UNP的角度看,select属于同步操作。因为select之后,进程还需要读写数据),从而提高系统的并发性!
(Java AIO(NIO.2))异步非阻塞IO:
在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。
1.3 异常
掌握Throwable继承体系。
Java异常体系:
Throwable(异常和错误的顶层父类)
|----- Error:错误类。表示的是程序在运行过程中出现的错误。错误的发生都属于系统级别。(JVM是运行操作系统上,JVM操作内存是需要借助操作系统,如果内在发生错误,会由操作系统反馈给JVM)
通常在程序中发生错误的原因是因为程序在书写时存在问题,而JVM运行有问题的代码就会引发内存出错。解决错误的方案:修改源代码
|----- Exception:异常类。程序在运行过程中,出现了异常现象:数组越界、类型转换异常等。通常在程序中如果发生了异常,是有专门针对异常处理的方案(处理方案是由开发人员自己制定)
程序中异常的发生通常是因为程序在操作数据时引发的,解决异常的方案是:声明、捕获
(学习以Exception为主,开发也主要以Exception为主)
提示:声明最终还需要使用捕获来处理异常
异常类的分类:
运行时异常:RuntimeException
编译时异常:Exception
异常的处理
声明:其实就是程序中遇到异常时,自己不处理,交给其它程序处理
关键字:throws
捕获:其实就是在程序中遇到异常时,不会交给其它程序处理,自己处理
关键字:try 、catch、finally
注意:1,在使用throw抛出异常代码的后面,不能书写任意代码。
2,如果使用try...catch...finally结构的,catch中抛出异常后面如果有其他语句,执行时先执行finally语句再去执行catch中的其他语句
3,try..catch..catch结构中必须按照子类到父类的顺序写
1.4 多线程
(1) 掌握Executors可以创建的三种线程池的特点及适用范围。
1.继承Thread类,重写父类run()方法
2.实现runnable接口
3.使用ExecutorService、Callable、Future实现有返回结果的多线程(JDK5.0以后)
(2) 多线程同步机制。
在需要同步的方法的方法签名中加入synchronized关键字。
使用synchronized块对需要进行同步的代码段进行同步。
使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁); 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池 等待队列中)。 取到锁后,他就开始执行同步代码(被synchronized修饰的代码);线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中 等待的某个线程就可以拿到锁执行同步代码了。这样就保证了同步代码在统一时刻只有一个线程在执行。
(3)线程的几种可用状态。
线程在执行过程中,可以处于下面几种状态:
就绪(Runnable):线程准备运行,不一定立马就能开始执行。
运行中(Running):进程正在执行线程的代码。
等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
睡眠中(Sleeping):线程被强制睡眠。
I/O阻塞(Blocked on I/O):等待I/O操作完成。
同步阻塞(Blocked on Synchronization):等待获取锁。
死亡(Dead):线程完成了执行。
(4)什么是死锁(deadlock)?
两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷入了无限的等待中。
(5)如何确保N个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
以上是关于javaEE面试宝典的主要内容,如果未能解决你的问题,请参考以下文章
Redis 面试宝典之 Redis 如何处理已经过期的数据?