java 面试整理持续整理中
Posted 村头老树下听风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 面试整理持续整理中相关的知识,希望对你有一定的参考价值。
String、StringBuffer与StringBuilder之间区别
String:在java中字符串属于java对象,java提供了string类来创建和操作字符串。但是值得注意的是string属于字符串常量,值是不会变的。
这就导致了每次对string的操作都会生成新的string对象。这样不仅效率低下,还比较浪费内存空间。所以为了解决这一问题,就有了stringBuffer和stringBuilder;
StringBuffer:字符串变量 线程安全的。可以多次操作不会产生新的未使用对象
stringBuilder:字符串变量 非线程安全的。可以多次操作不会产生新的未使用对象
但是在速度方面,stringBuilder > stringBuffer > String
所以多数情况下使用stringBuilder,但是如果是程序要求线程安全的情况下就必须使用StringBuffer
总结:
如果要操作少量数据则使用String
多线程字符串缓冲区下操作大量数据用StringBuffer
单线程字符串缓冲区下操作大量数据用StringBuilder
fail-fast vs fail-save
同步修改/并发修改:当一个或多个线程正在遍历一个集合collection,此时另一个线程修改了集合的内容(增加、删除或修改),这就是并发修改/同步修改
fail-fast机制:当一个线程在遍历一个集合时,当集合结构被修改,会抛出concurrent modification exception
fail-fast在两种情况下抛出concurrent modification exception
1、单线程下,在遍历它的过程修改了结构,注意:remove()方法会让expectModcount 和modcount相等,所以不会抛异常。
2、多线程下,当一个线程在遍历集合,而另一个线程对该集合结构进行了修改。
fail-safe机制:对任何集合的修改都会在复制的集合上进行修改,因此不会抛出concurrent modification excption
fail-safe机制有两个问题;
1、需要复制集合,产生大量无效对象,开销大
2、无法保证读取到的数据是否为目前原数据结构中的数据
happens-before:
如果两个操作之间存在happens-before关系,那么前一个操作的结果就会对后面一个操作可见。(如果一个操作的结果对另一个操作可见,那么他们之间存在happens-before.)
happens-before规则:
1、程序次序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
2、监视器锁规则:对一个监视器锁的解锁,happens-before于随后对这个监视器锁的加锁。
3、volatile变量规则:对于一个volatile域的写,happens-before于任意后续对这个volatile域的读。
4、传递性:如果A happens-before B,B happens-before C ,那么 A happens-before C。
5、start规则:如果线程A 执行操作ThreadB.start()【启动线程B】,那么A 线程的ThreadB.start()操作happens-before于线程B的任意操作
6、join规则:如果线程A 执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于ThreadB.join操作成功返回。
volatile vs synchronized
java多线程有三大特性:原子性、可见性、有序性
原子性:是指线程的多个操作是一个整体,不能被分割。要么就不执行,要么就全部执行,中间不能被打断。
可见性:是指线程之间的可见性。就是一个线程修改后,其他线程立马能够知道。
有序性:为了提高执行效率,java的编译器和处理器可以对指令进行重新排序,重新排序会影响多线程并发的正确性,有序性就是保证不进行重新排序。
volatile关键字的作用就是保证可见性和有序性,但不保证原子性。如果一个共享变量被volatile修饰,那么当有一个线程修改了这个共享变量后,其他线程也立马进行修改;
volatile同时能禁止指令重新排序,在指令重排序优化时,在volatile变量之前的指令不能在volatile之后执行,反之同理。
synchronized关键字提供了同步锁的概念,被synchronized修饰的代码可以防止被多个线程同时执行,因为synchronized保证了在同一时刻只能有一个线程执行同步代码块,
所以执行同步代码块的操作相当于单线程。那么线程的三大特性都能保证了。
volatile和synchronized的区别:
1、volatile只能用在变量,范围较小。而synchronized则可以用在变量、方法。类、同步代码块等,范围较大。
2、volatile只能保证可见性与有序性,不能保证原子性。而synchronized三大特性都可以。
3、volatile不会造成线程阻塞,而synchronized会造成线程阻塞。
request.getParameter()、request.getInputStream()、request.getReader():
request.getParameter()、request.getInputStream()、request.getReader()这三个方法都是从request对象得到提交的数据,但各有不同;
request.getParameter():form的一个关键属性enctype=application/x- www-form-urlencoded,这也是默认的编码方式。编码后的结果通常是
field1=value1&field2=value2...等。
例:name=aaa&pwd=bbb;
这应该属于最常用的获取提交数据,但弊端是对于传输较大块的二进制数据显得力不从心。
request.getInputStream()、request.getReader(): form的编码方式为: "multipart/form-data"
浏览器可以很容易将表单内的数据和文件放在一起发送。这种编码方式先定义好一个不可能在数据中出现的字符串作为 分界符,然后用它将各
个数据段分开,而对于每个数据段都对应着 html 页面表单中的一个 Input 区,包括一个 content-disposition 属性,说明了这个数据段的一些
信息,如果这个数据段的内容是一个文件,还会有 Content-Type 属性,然后就是数据本身,如果以这种方式提交数据就要用
request.getInputStream()或request.getReader()得到 提交的数据,用 request.getParameter()是得不到提交的数据的。
值得注意的是:request.getParameter()、request.getInputStream()、request.getReader()三个方法是有冲突的,因为流只能被读一次。
以上是关于java 面试整理持续整理中的主要内容,如果未能解决你的问题,请参考以下文章