JAVA面试题集及解答

1、如何决定使用 HashMap 还是 TreeMap

2、HashMap的实现原理

3、HashSet的实现原理

4、Array 和 ArrayList 有何区别

  • Array可以容纳基本类型和对象,而ArrayList只能容纳对象。

  • 补充:Array运用多态的特性,如果定义数组类型的时候定义为父类,而存进数组为该父类的子类的话可以存储不同类型的对象,但是一般不推荐,放进去,再取出来的时候,就不知道这个该当作哪个子类来用了,所以必须当作父类来用。你可以用强转的方法,不过不建议。ArrayList可以存储不同类型的数据,一般为了类型安全这样子创建List<类型> list = new ArrayList<>() 

  • Array是指定大小后不可变的,而ArrayList大小是可变的(动态扩容)。 

  • Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等

5、Iterator 和 ListIterator 有什么区别

  • Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。 

  • Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。 

  • ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

6、进程与线程的区别

7、守护线程

  守护线程,专门用于服务其他的线程,如果其他的线程(即用户自定义线程)都执行完毕,连main线程也执行完毕,那么jvm就会退出(即停止运行)——此时,连jvm都停止运行了,守护线程当然也就停止执行了。
  守护线程拥有自动结束自己生命周期的特性,JVM 中的垃圾回收线程就是典型的守护线程,如果说不具备该特性,当 JVM 要退出时(停止运行),由于垃圾回收线程还在运行着,就会导致程序无法退出。通常来说,守护线程经常被用来执行一些后台任务,但是呢,你又希望在程序退出时,或者说 JVM 退出时,线程能够自动关闭,此时,守护线程是你的首选。
 
8、runnable 和 callable 有什么区别
  Callable接口比Runnable接口要新一点,它是在 Java 5 的时候发行的。尽管Callable跟Runnable接口都是设计来代表一个任务(task), 这个任务可以被任意线程执行, 但两者间还是有一些明显的差异. 在我看来, 最主要的差异在于Callable可以在内部的call()方法返回执行的结果, 而Runnable则不行另一个明显的差别是: 是否有能力抛出checked exception. Callable可以抛出checked exception因为它的call()方法抛出了这个异常。
  另外 FutureTask跟Callable一起使用可以来获取异步任务中的结果。多线程返回执行结果是很有用的一个特性,因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。而Callable+Future/FutureTask却可以获取多线程运行的结果,可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务,真的是非常有用。


线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。

  • 创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。

  • 就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

  • 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

  • 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。

  • 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪   

 10、notify()和 notifyAll()有什么区别?

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

  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。

  • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

 11、线程池都有哪些状态

12、转发(forword)和重定向(redirect)的区别

转发:

  • 转发地址栏路径不变
  • 只能访问当前服务器上的资源
  • 转发只是一次请求,可以使用request对象来共享数据

重定向:

  • 地址栏发生变化
  • 可以访问其他站点(服务器)的资源
  • 重定向是两次请求,不能使用request对象共享资源

菜鸟试水,待续——

posted @ 2020-03-03 19:19  三杯弄剑  阅读(126)  评论(0)    收藏  举报