Java面试(二)
1 同步方法 VS 同步代码块:
java中,每一个对象都有一把锁,线程用synchronized获取对象上的锁。
非静态同步方法:锁是类的对象的锁。
静态同步方法:锁的是类本身。
同步方法块:锁是可以选择的。所以能更加精确的控制。粒度更细致,可以更精确的控制对象锁。
2 确保N个线程可以访问N个资源而不死锁?
指定资源获取顺序。所有线程都按照同样的顺序请求资源。
3 Java集合框架接口
Collection: 代表一组对象。
Set:
List:
Map:
4 为什么集合类没有实现Cloneable和Serializable接口?
应该集合中的元素自己实现,定义自己的行为。
5 什么是迭代器(Iterator)?
它可以使得对于序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的。只要拿到这个对象,使用迭代器就可以遍历这个对象的内部.
主要方法: hasNext( ) / next( ) / remove(删除后,指向下一个)
迭代器优点:提供统一的迭代方法;可以在对客户透明的情况下,提供不同的迭代方法;快速失败机制,防止多线程下迭代的不安全操作。
6 快速失败&&安全失败:
(注意:以下的集合的修改是指,集合结构的变化,增加、删除节点,修改某一个节点的对象的内容不算是集合结构的变化。)
快速失败(fail-fast):
在用迭代器遍历一个集合时,遍历过程中,其他线程对集合内容进行修改(增,删),则
会抛出异常ConCurrentModificationException。迭代器在遍历的时候直接访问集合的元素,并且在遍历过程中使用一modCount变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器用hasNext()/next()遍历一个元素的之前,都会检测modCount,如果改过,就抛出异常。Java.util包中的集合都是快速失败的,不能在多线程下发生并发修改。
安全失败(fail-safe):
如果在迭代器遍历concurrentHashMap的过程中,往map中增/删/改,是不会抛出异常。但是会导致不一致的问题。采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问,而是先复制原集合内容,在拷贝的集合上进行遍历。缺点是:不能访问修改后的内容,
java.util.concurrent包下的容器都是安全失败的,可以在多线程下并发使用,并发修改。
安全失败迭代器在迭代中被修改,不会抛出任何异常,因为它是在集合的克隆对象迭代的,所以任何对原集合对象的结构性修改都会被迭代器忽略,但是这类迭代器有一些缺点,其一是它不能保证你迭代时获取的是最新数据,因为迭代器创建之后对集合的任何修改都不会在该迭代器中更新,还有一个缺点就是创建克隆对象在时间和内存上都会增加一些负担。
7 Iterator和ListIterator区别
Iterator可以用来遍历Set,Map和List,但是ListItrator只能用来遍历List。
Iterator对集合只能向前遍历(hasNext(), Next()).ListIterator是双向都可以遍历。
ListIterator实现了Iterator接口,并包含了其他功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引。
8 HashMap的工作原理
键值对形式存储元素。需要一个hash函数,使用hashCode() 和equals()方法来向集合添加,检索元素。
Put(key, value) : 计算key的hash值,然后把键值对存储在集合中合适对索引上。Entry存储在LinkedList中,所以如果存在entry,它使用equals()方法来检查传递的key是否已经存在,如果存在,它会覆盖value,如果不存在,它会创建一个新的entry然后保存。
Get(key): 首先是用hashcode找到桶,然后key,equals(),判断是否相等。
重要特性是:容量(默认初始值是32),负载因子(默认是0.75),阈值是负载因子乘以容量,如果大于阈值,就会扩容。扩容极限。建议如果在开始的时候知道元素的个数,设定初始值。
容量:桶的数量。
负载因子:有多少桶被占用了。
9 HashMap VS Hashtable
都实现了Map接口,很相似。有如下不同点:
hashMap的键和值是null,hasttable不允许键或值是null.
HashMap不是同步的(适合单线程,是快速失败的),hashtable(适合多线程)是同步的。
HashMap提供了键集合;而Hashtable提供了对键的枚举。
Hashtable是遗留的类。
10 数组(Array)和列表(ArrayList)有什么区别?各自的应用场合?
数组:可以存放基本类型+对象类型;列表:only对象类型(因为LIst里的元素必须继承自object)。
Array大小固定的; ArrayList是动态变化的。
ArrayList提供了很多方法: addAll(), removeall(), iterator()等等。
对于基本类型,集合使用自动装箱来减少代码量;但是,当处理固定大小的基本数据类型的时候,这种方式比较慢。
11 ArrayList VS LinkedList
都是实现了List接口。
ArrayList底层是数组。可以以o(1)时间复杂度对元素进行随机访问。
LinkedList: 是以元素列表的形式存储数据,链表。查找的时间复杂度是0(n),但是插入,添加,删除更快。
LinkedList更费内存,因为要存储指针。
12 Comparable 和 Comparator?
实现了Comparable,表明可以比较元素,可以用SORT排序。Comparator看做是算法的实现,将算法和数据分离。
用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
Comparable接口:只包含了一个compareTo()方法,可以进行排序。
Comparator接口:包含compare()和 equals()两个方法。
二者用法不同:比如在集合中的元素可以自己实现Comparable,这样就可以用Collections.sort()调用进行排序;如果想定义格外的排序方法,可以实现Comparator接口,Collections.sort()另外一个重载方法可以接收一个compareator.
13 java集合类的最佳实践
根据需要正确的选择要使用的。比如:元素大小固定,事先知道,用 Array 而不是ArrayList
对于一些容器(hashMap):如果知道容量,可以提前给一个初始容量,避免扩容,再哈西的性能损耗。
为了类型安全,可读性和健壮性总是要使用泛型,泛型可以避免ClassCastException
用JDK提供的不变类(immutable class)作为Map的键可以避免为我们的类实现hashCode() 和
equals() 方法。
编程的时候接口优于实现。
底层的集合实际上是空的情况下,返回长度是0的集合或数组,不要返回null。
14 java优先级队列(Priority Queue)
每次出队的是优先级最高的。是用大顶堆实现的。要提供一个比较器comparator,否则按照自然顺序排列。
Queue<Test> priQueue = new PriorityQueue<Test>(11,OrderIsdn); // 指定一个comparator
// 默认队列大小是11
Test t1 = new Test("t1",1);
Test t3 = new Test("t3",3);
priQueue.add(t3);
基于优先级堆无界队列,它的元素按照自然顺序排序,在创建的时候可以提供一个比较器。不允许null值。不是线程安全的,入队和出对的时间复杂度是log(n).
15 什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。
如何做到线程安全:
四种方式
sychronized关键字
1. sychronized method(){} // 同步方法
2. sychronized (objectReference)
{/*block*/} // 同步块
3. static synchronized method(){} // static 同步方法
4. sychronized(classname.class) // 指定同步类
其中1和2是代表锁当前对象,即一个对象就一个锁,3和4代表锁这个类,即这个类的锁。要注意的是sychronized method()不是锁这个函数,而是锁对象,即:如果这个类中有两个方法都是sychronized,那么只要有两个线程共享一个该类的reference,每个调用这两个方法之一,不管是否同一个方法,都会用这个对象锁进行同步。
注意:long 和double是简单类型中两个特殊的咚咚:java读他们要读两次,所以需要同步。
16 如何权衡用无序数组还是有序数组
有序数组查找的时间复杂度是O(logn),但是插入操作的时间复杂度是O(n).
无序的是O(n),但是插入的时间复杂度是O(1).
17 Java中,int 是否是类型安全的。
Int 的赋值是原子的,但是i++不是。
18 HashSet VS TreeSet
HashSet 元素是无序的,最多放入一个NULL值,add(), remove(), contains(), 这些方法的复杂度都是O(1)
TreeSet: 树形结构实现,元素是有序的,不能放入NULL值。 Add(), remove(), contains()复杂度是log(n).
Java面试(二)的更多相关文章
- [Java面试二]Java基础知识精华部分.
一:java概述(快速浏览): 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名 ...
- java面试二
技术交流群: 233513714 126.什么是ORM?答:对象关系映射(Object-Relational Mapping,简称ORM)是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题 ...
- java面试(二)
1.java常见的容器 几乎所有的容器都继承了Collecton接口,包括List.Set.Queue.Map List包括Vector.ArrayList.LinkedList, Set包 ...
- Java 面试知识点解析(二)——高并发编程篇
前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...
- java面试总躲不过的并发(二):volatile原理 + happens-before原则
一.happens-before原则 同一个线程中的,前面的操作 happens-before 后续的操作.(即单线程内按代码顺序执行.但是,在不影响在单线程环境执行结果的前提下,编译器和处理器可以进 ...
- Java面试集合(二)
前言 大家好,给大家带来Java面试集合(二)的概述,希望你们喜欢 二 1.请问线程有哪些状态? 新建状态(New) 就绪状态(Runnable) 运行状态(Running) 阻塞状态(Blocked ...
- Java面试知识点之线程篇(二)
前言:接上篇,这里继续对java线程相关知识点进行总结. 1.notify和notifyall的区别 notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象的 ...
- java面试宝典(蓝桥学院)
Java面试宝典(蓝桥学院) 回答技巧 这套面试题主要目的是帮助那些还没有java软件开发实际工作经验,而正在努力寻找java软件开发工作的学生在笔试/面试时更好地赢得好的结果.由于这套试题涉及的范围 ...
- JAVA面试精选【Java基础第一部分】
这个系列面试题主要目的是帮助你拿轻松到offer,同时还能开个好价钱.只要能够搞明白这个系列的绝大多数题目,在面试过程中,你就能轻轻松松的把面试官给忽悠了.对于那些正打算找工作JAVA软件开发工作的童 ...
- Java面试必备知识
JAVA面试必备知识 第一,谈谈final, finally, finalize的区别. 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可 ...
随机推荐
- Linux软件安装(二)
1. 安装软件时,如果依赖的文件是 .so 类型的文件(so文件是谋个文件的小功能模块,如果php.ini中设置的模块引用就是 .so文件) ,这时被依赖的软件要安装完整的软件,一般可以根据 .so ...
- neutron ovs+vxlan
title: Neutron ovs+vxlan date: 2017-04-26 23:37 tags: Network 主机网卡配置 controller: ens160:192.168.11.1 ...
- opencv:图像的腐蚀和膨胀
1.图像的腐蚀 图像的腐蚀和膨胀都是相对于像素值高(白色方向)说的,腐蚀简单的说就是白色”被腐蚀“了,也就是像素值低(黑色方向)的变多,白色变少. 腐蚀的原理是利用一个内核对图像进行卷积(扫描),内核 ...
- poj2446
题解: 二分图匹配 看看是否能达到目标 代码: #include<cstdio> #include<cstring> #include<algorithm> #in ...
- 2017.11.15 Add a parameter –serial <serial no> to the Target field.
1 exe创建快捷方式,并且加后缀 program --serial 50114130 这是Win里面的一种调用说明. Please note that the programming logs ...
- SVN的详细简单操作
SVN服务器搭建和使用(一) http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407610.html SVN服务器搭建和使用(二) ht ...
- will-change 提高页面滚动、动画等渲染性能
一.先来看一个例子 视差滚动现在不是挺流行的嘛,然后Chris Ruppel当其使用background-attachment: fixed实现背景图片不随滚动条滚动而滚动效果的时候,发现,页面的绘制 ...
- Delphi XE4 Upate1 更新升级记录.
一直没时间,这两天折腾了一下 升级了. 其实也可能修了老bug 引入新bug. 呵呵. 看看Emb 都修了什么吧. 我干脆是重新安装的. 虽然官方也有一个单独的update.exe. 从这些bu ...
- c++ wchar_t 与char 直接的转换【转】
http://blog.163.com/tianshi_17th/blog/static/4856418920085209414977/ 实现了一下 #include "stdafx.h&q ...
- Ubuntu 16.04 为 PHP7 添加 memcached 以及 redis 扩展
切换到 PHP 7 之后,网站的速度大幅提升,不过通常的扩展可能某一个就还没有支持 PHP7 Memcached 比如说我现在使用了最新的 Ubuntu 16.04,虽然内置了 PHP 7 源,但 m ...