[Java常考面试题-牛客网] 第11-20题
第11题:进程和线程的区别是什么?
线程是CPU调度的基本单元。
进程是 正在运行的程序,进程包含1个或多个线程。
不同的进程之间相互独立,而在同一个进程中的线程共享同一块内存区域。
第12题:创建线程有几种不同的方式?你喜欢哪一种?为什么?
有4种方式来创建线程:
1. 继承Thread类
2. 实现Runnable接口
3. 使用Executor框架来创建线程池。
4. 实现Callable接口。
继承Thread类的会简单一点。但 Java只支持单继承,所以不是很方便,因此实现Runnable接口的方式会更加受欢迎。
具体 操作可以参考 http://www.importnew.com/21136.html
第13题:概括地解释下 线程的几种可用状态。
参考自:
https://www.nowcoder.com/questionTerminal/f665a4c853b841339e7181a0fdbacfa8?pos=387&orderByHotValue=1
1. 新建(new): 新创建了一个线程对象。
2. 可运行(runnable):线程对象创建后,其他线程(如main线程)调用了该线程对象的start()方法,然后这个线程被放到了可运行的线程池种,等待被线程调度(scheduler)选中,获取cpu的使用权。
3. 运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。
4. 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu的使用权(timeslice),暂时停止运行。只有线程重新回到可运行状态,它才能再次获得cpu的timeslice,从而进入运行状态。
阻塞的情况分3种:
1)等待阻塞:运行(running)状态的线程执行 o.wait()方法,JVM会把该线程放入等待队列(waiting queue)种。
2)同步阻塞:运行(running)状态的线程无法获取某个对象的同步锁时(因为被别的线程占用),JVM会把该线程放入锁池(lock pool)中。
3)其他阻塞:运行(running)状态的线程执行了 Thread.sleep(long ms) 或 t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。 只有当 sleep()状态超时,join()等待线程中值或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
5. 死亡(dead):线程run()、main()方法执行结束,或者因 异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
第14题: 同步方法 和 同步代码块的 区别是什么?
参考:http://blog.****.net/h_gao/article/details/52266950
1. 同步方法默认用this(也就是当前类的对象)作为锁,作用范围是整个方法。例如,public synchronized void methodA() {...}
2. 同步代码块由程序员确定哪个对象作为锁,和 在 哪个范围的代码块加锁。例如,synchronized (str) {...}
同步方法的锁的范围比较大,同步代码块的比较小。锁的范围越小越好,所以同步代码块性能更好一些。
第15题:在监视器(monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?
参考:http://www.cnblogs.com/ygj0930/p/6561667.html
监视器是一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量。
synchronized又叫内置锁,是通过monitor的取用与释放来实现的。一个对象的monitor是唯一的。
现在假设有代码块: syncrhoized(Object lock){
同步代码...;
}
它在字节码文件中被编译为:monitorenter;//获取monitor许可证,进入同步块
同步代码...
monitorexit;//离开同步块后,释放monitor许可证
第16题 什么是死锁(deadlock)?
死锁就是一系列获得了部分资源的进程,等待获取一写被别的进程占用的资源,形成的一种僵局。
1. 互斥条件(mutual exclusion):在某个时刻,有些资源只能被一个进程占用。
2. 拥有和等待(hold and wait):一个进程占有了至少一个资源,并且提出了新的资源请求。
3. 不可剥夺条件(no preemption):只能由占有资源的进程自己释放自己的资源。
4. 循环等待条件(circular wait):出现了环路等待。
第17题: 如何确保N个线程可以访问N个资源同时又不导致死锁?
一种简单的方法:强制指定获取获取锁的顺序。
第18题:Java集合类框架的基本接口有哪些?
参考自 牛客网。
总共有2大接口:Collection和Map
(一)Collection(元素集合,代表一组对象,每一个对象都是它的子元素)
1. List接口继承了Collection接口,是有序的元素集合。
ArrayList和LinkList是类,它们实现了List接口。
1.1)ArrayList底层采用数组存储,因此适合查询,不适合增删。
1.2)LinkList底层采用双向链表,适合增删,不适合查询。
2. Set接口继承了Collection接口,是无序的元素集合。
HashSet实现了Set接口。
TreeSet实现了SortedSet接口(图上没有画出来)。无序不可重复,但可排序。
(二)Map(键值对集合,把key映射到value上,且键不能重复)
1. HashMap和HashTable实现了Map,其中HashTable是线程安全的,但是HashMap性能更好。
2. TreeMap实现了SortedMap接口(图上没画出来)。无序,不可重复,但可排序。
第19题:为什么集合类没有实现Cloneable和Serializable接口?
克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
[序列化:为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。]
不是很懂序列化是什么意思。
第20题:什么是迭代器(iterator)?
迭代器总是用同一种逻辑来遍历集合,使得客户端自身不需要维护集合的内部结构,所有的状态都有Iterator来维护。