Java面试(五)

1、多线程有几种实现方法?同步有几种实现方法?

2、启动一个线程是用 run()还是 start()?

3、当一个线程进入一个对象的一个 synchronized 方法后,其它线程是否可进入此对象的其它方法?

4、线程的基本概念、线程的基本状态以及状态之间的关系?

5、简述 synchronized 和 java.util.concurrent.locks.Lock 的异同 ?

6、ArrayList 和 Vector 的区别

7、HashMap 和 Hashtable 的区别

8、List 和 Map 区别?

9、List, Set, Map 是否继承自 Collection 接口?

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


1、多线程有几种实现方法?同步有几种实现方法?

多线程有两种实现方法,分别是继承 Thread 类与实现 Runnable 接口

同步的实现方面有两种,分别是 synchronized,wait 与 notify

wait():使一个线程处于等待状态,并且释放所持有的对象的 lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉 InterruptedException 异常。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

2、启动一个线程是用 run()还是 start()?

启动一个线程是调用 start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。

3、当一个线程进入一个对象的一个 synchronized 方法后,其它线程是否可进入此对象的其它方法?

分几种情况:

1.其他方法前是否加了 synchronized 关键字,如果没加,则能。

2.如果这个方法内部调用了 wait,则可以进入其他 synchronized 方法。

3.如果其他个方法都加了 synchronized 关键字,并且内部没有调用 wait,则不能。

4.如果其他方法是 static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法 用的是 this。

4、线程的基本概念、线程的基本状态以及状态之间的关系?

一个程序中可以有多条执行线索同时执行,一个线程就是程序中的一条执行线索,每个线程上都关联有要执行的代码,即可以有多段程序代码同时运行,每个程序至少都有一个线程,即 main 方法执行的那个线程。如果 只是一个 cpu,它怎么能够同时执行多段程序呢?这是从宏观上来看的,cpu一会执行a 线索,一会执行 b 线索,切换时间很快,给人的感觉是 a,b 在同时执行,好比大家在同一个办公室上网,只有一条链接到外部网线, 其实,这条网线一会为 a 传数据,一会为 b 传数据,由于切换时间很短暂,所以,大家感觉都在同时上网。

状态:就绪,运行,synchronize 阻塞,wait 和 sleep 挂起,结束。wait 必须在 synchronized 内部调用。
调用线程的 start 方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为运行状态,遇到 synchronized语句时,由运行状态转为阻塞,当 synchronized 获得锁后,由阻塞转为运行,在这种情况可以调用 wait 方法转为挂起状态,当线程关联的代码执行完后,线程变为结束状态 。

5、简述 synchronized 和 java.util.concurrent.locks.Lock 的异同 ?

主要相同点:Lock 能完成 synchronized 所实现的所有功能
主要不同点:Lock 有比 synchronized 更精确的线程语义和更好的性能。synchronized 会自动释放锁,而 Lock一定要求程序员手工释放,并且必须在 finally 从句中释放。Lock 还有更强大的功能,例如,它的 tryLock 方法可以非阻塞方式去拿锁。

6、ArrayList 和 Vector 的区别

这两个类都实现了 List 接口(List 接口继承了 Collection 接口),

他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,,并且其中的数据是允许重复的,这是 HashSet 之类的集合的最大不同处,HashSet 之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素(本来题目问的与 hashset 没有任何关系,但为了说清楚 ArrayList 与 Vector 的功能,我们使用对比方式,更有利于说明问题)。

接着才说 ArrayList 与 Vector 的区别,这主要包括两个方面:

(1)同步性:
Vector 是线程安全的,也就是说是它的方法之间是线程同步的,而 ArrayList 是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用 ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。

备注:对于 Vector&ArrayList、Hashtable&HashMap,要记住线程安全的问题,记住 Vector 与 Hashtable 是旧的, 是 java 一诞生就提供了的,它们是线程安全的,ArrayList 与 HashMap 是 java2 时才提供的,它们是线程不安全的。

(2)数据增长:
ArrayList 与 Vector 都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加 ArrayList 与 Vector 的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector 默认增长为原来两倍,而ArrayList 的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的 1.5 倍)。ArrayList 与 Vector 都可 以设置初始的空间大小,Vector 还可以设置增长的空间大小,而 ArrayList 没有提供设置增长空间的方法。
总结:即 Vector 增长原来的一倍,ArrayList 增加原来的 0.5 倍。

7、HashMap 和 Hashtable 的区别

HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,主要区别在于 HashMap 允许空(null)键值(key),由于非线程安全,在只有一个线程访问的情况下,效率要高于 Hashtable。
HashMap 允许将 null 作为一个 entry 的 key 或者 value,而 Hashtable 不允许。
HashMap 把 Hashtable 的 contains 方法去掉了,改成 containsvalue 和 containsKey。因为 contains 方法容易让人引起误解。

8、List 和 Map 区别?

一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,List 中存储的数据是有顺序,允许重复,Map 中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。

9、List, Set, Map 是否继承自 Collection 接口?

List,Set 是,Map 不是

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

List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存 key-value 值,value 可多值。

首先,List 与 Set 具有相似性,它们都是单列元素的集合,所以,它们有一个功共同的父接口,叫 Collection。Set 里面不允许有重复的元素,所谓重复,即不能有两个相等(注意,不是仅仅是相同)的对象 ,即假设 Set 集合中有了一个 A 对象,现在我要向 Set 集合再存入一个 B 对象,但 B 对象与 A 对象 equals 相等,则 B 对象存储不进去,所以,Set 集合的 add 方法有一个 boolean 的返回值,当集合中没有某个元素,此时 add 方法可成功加入该元 素时,则返回 true,当集合含有与某个元素 equals 相等的元素时,此时 add 方法无法加入该元素,返回结果为 false。 Set 取元素时,没法说取第几个,只能以 Iterator 接口取得所有的元素,再逐一遍历各个元素。

List 表示有先后顺序的集合, 注意,不是那种按年龄、按大小、按价格之类的排序。当我们多次调用 add(Obj e)方法时,每次加入的对象就像火车站买票有排队顺序一样,按先来后到的顺序排序。有时候,也可以插队,即 调用 add(int index,Object)方法,就可以指定当前对象在集合中的存放位置。一个对象可以被反复存储进 List 中,每调用一次 add 方法,这个对象就被插入进集合中一次,其实,并不是把这个对象本身存储进了集合中,而是在集 合中用一个索引变量指向这个对象,当这个对象被 add 多次时,即相当于集合中有多个索引指向了这个对象,如 图 x 所示。List 除了可以以 Iterator 接口取得所有的元素,再逐一遍历各个元素之外,还可以调用 get(index i)来明 确说明取第几个。

Map与List和Set不同,它是双列的集合,其中有put方法,定义如下:put(obj key,obj value),每次存储时, 要存储一对 key/value,不能存储重复的 key,这个重复的规则也是按 equals 比较相等。取则可以根据 key 获得相应的 value,即 get(Object key)返回值为 key 所对应的 value。另外,也可以获得所有的key 的结合,还可以获得所有的 value 的结合,还可以获得 key 和 value 组合成的 Map.Entry 对象的集合。



原文链接:https://zhuanlan.zhihu.com/p/347787861