JAVA面试精髓(初级篇)

IO、集合、多线程

1、ArrayList、Vector、LinkedList的存储性能和特性
答,ArrayList 和Vector他们底层的实现都是一样的,都是使用数组方式存储数据,  Vector中的方法由于添加了synchronized修饰,也就是加了同步锁,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。
LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
       
2、List、Set、Map是否继承自Collection接口? 
Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法。 Set 和List 都继承了Conllection;Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只 是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责) 

 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。

a、Collection 和 Map 的区别

容器内每个为之所存储的元素个数不同。
Collection类型者,每个位置只有一个元素。
Map类型者,持有 key-value pair,像个小型数据库。

b、各自旗下的子类关系

Collection
     --List:将以特定次序存储元素。所以取出来的顺序可能和放入顺序不同。
           --ArrayList / LinkedList / Vector
     --Set : 不能含有重复的元素
           --HashSet / TreeSet(可排序)
      Map
     --HashMap  线程不安全,性能快,不同步,内部结构是哈希表,允许null作为键,null作为值
     --HashTable 线程安全,但慢,多线程才会考虑使用,同步,内部结构是哈希表,不允许null作为键,null作为值
     --TreeMap  内部结构是二叉树,不同步,可以对map的键进行排序

3、List、Map、Set三个接口存取元素时,各有什么特点? 

Set里面不允许有重复的元素,
存元素:add方法有一个boolean的返回值,当集合中没有某个元素,此时add方法可成功加入该元素时,则返回true;当集合含有与某个元素equals相等的元素时,此时add方法无法加入该元素,返回结果为false。
取元素:没法说取第几个,只能以Iterator接口取得所有的元素,再逐一遍历各个元素。

List表示有先后顺序的集合,
存元素:多次调用add(Object)方法时,每次加入的对象按先来后到的顺序排序,也可以插队,即调用add(int index,Object)方法,就可以指定当前对象在集合中的存放位置。
取元素:方法1:Iterator接口取得所有,逐一遍历各个元素

        方法2:调用get(index i)来明确说明取第几个。

Map是双列的集合,存放用put方法:put(obj key,obj value),每次存储时,要存储一对key/value,不能存储重复的key,这个重复的规则也是按equals比较相等。
取元素:用get(Object key)方法根据key获得相应的value。

        也可以获得所有的key的集合,还可以获得所有的value的集合,

        还可以获得key和value组合成的Map.Entry对象的集合。
4、请说出与线程同步以及线程调度相关的方法。

-wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

-sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;
 
-notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
 
-notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态; 

5、编写多线程程序有几种实现方式? 
1.继承Thread类实现多线程
2.实现Runnable接口方式
3.使用ExecutorService、Callable、Future实现有返回结果的多线程
4.使用匿名内部类
5.线程池

Thread 类中的start() 和 run() 方法有什么区别?
这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

6、简述synchronized 和java.util.concurrent.locks.Lock的异同?
简要答案:
   1.Lock能完成几乎所有synchronized的功能,并有一些后者不具备的功能,如锁投票、定时锁等候、可中断锁等候等
   2.synchronized 是Java 语言层面的,是内置的关键字;Lock 则是JDK 5中出现的一个包,在使用时,synchronized 同步的代码块可以由JVM自动释放;Lock 需要程序员在finally块中手工释放,如果不释放,可能会引起难以预料的后果(在多线程环境中)。
7、hash碰撞以及hash算法、如何解决哈希冲突 
9、HashMap的存储原理,需要了解HashMap的源码。 
12、Hashtable,HashMap,ConcurrentHashMap 底层实现原理与线程安全问题 

ConcurrentHashMap是使用了锁分段技术来保证线程安全的。

锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 

ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。

ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的(也就是默认提升了16倍)。

13、Hash冲突怎么办?哪些解决散列冲突的方法? 
14、讲讲IO里面的常见类,字节流、字符流、接口、实现类、方法阻塞。 

字节流
字节流主要是操作byte类型数据,也byte数组为准,主要操作类就是
·字节输出流:OutputStream
·字节输入流:InputStream
字符流
在程序中一个字符等于2个字节,那么java提供了Reader、Writer两个专门操作字符流的类。
·字符输出流:Writer
·字符输入流:Reader
字节-字符转换流
OutputStreamWriter和InputStreamReader
在整个IO包中,实际上就是字节流和字符流,但是除了这两个流之外,还存在一组字节流-字符流的转换类。
[java] view plaincopyprint?
•OutputStreamWriter:是Writer的子类,将输出的字符流转换为字节流。即:将一个字符流的输出对象变为字节流的输出对象  
•InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即:将一个字节流的输入对象变为字符流的输入对象
15、讲讲NIO。

思路:分而治之,将任务拆分开来,由专门的人负责专门的任务。
具体来讲,银行专门指派一名职员A,A的工作就是每当有顾客到银行,他就递上表格让顾客填写,每当有顾客填好表后,A就将其随机指派给剩余的9名职员完成后续步骤。 

16、递归读取文件夹下的文件,代码怎么实现

/** 
 * 递归读取文件夹下的 所有文件 
 * 
 * @param testFileDir 文件名或目录名 
 */  
private static void testLoopOutAllFileName(String testFileDir) {  
    if (testFileDir == null) {  
        //因为new File(null)会空指针异常,所以要判断下  
        return;  
    }  
    File[] testFile = new File(testFileDir).listFiles();  
    if (testFile == null) {  
        return;  
    }  
    for (File file : testFile) {  
        if (file.isFile()) {  
            System.out.println(file.getName());  
        } else if (file.isDirectory()) {  
            System.out.println("-------this is a directory, and its files are as follows:-------");  
            testLoopOutAllFileName(file.getPath());  
        } else {  
            System.out.println("文件读入有误!");  
        }  
    }  
}  


17、常用的线程池模式以及不同线程池的使用场景 
18、newFixedThreadPool此种线程池如果线程数达到最大值后会怎么办,底层原理。 
19、了解可重入锁的含义,以及ReentrantLock 和synchronized的区别 

20、atomicinteger和volatile等线程安全操作的关键字的理解和使用 
 对于可见性,Java提供了volatile关键字来保证可见性。
 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。但是不能保证原子性
另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性
atomicinteger:保证了全局变量的原子性

21、进程和线程的区别 

22、什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
23、同步和异步,阻塞和非阻塞 
       同步:一个服务的完成需要依赖其他服务时,只有等待被依赖的服务完成后,才算完成,这是一种可靠的服务序列。要么成功都成功,失败都失败,服务的状态可以保持一致
       异步:一个服务的完成需要依赖其他服务时,只通知其他依赖服务开始执行,而不需要等待被依赖的服务完成,此时该服务就算完成了。被依赖的服务是否最终完成无法确定,一次它是一个不可靠的服务序列
阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务,函数只有在得到结果之后才会返回。
      非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

1、同步阻塞:小明啥都不干等奶茶。
2、同步非阻塞:小明一边玩手机一边等奶茶。
3、异步阻塞:小明拿着小票啥都不干等着奶茶妹告诉他奶茶好了
4、异步非阻塞:小明拿着小票玩着手机等着奶茶妹告诉他奶茶好了

24、多线程的三大特性
1、原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
2、可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
3、有序性:程序执行的顺序按照代码的先后顺序执行。
25、怎么禁止java的反射机制

java默认走的是无参构造函数,把对象的无参构造函数私有化,即可

猜你喜欢

转载自blog.csdn.net/w_qqqqq/article/details/82500381