欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

2020Java开发工程师面试知识储备(三)java常用类(待补充),多线程

程序员文章站 2022-08-18 08:45:52
功利性得去找了下面试题库,发现一个讲面试题的教程,觉得讲得不错,教程地址在这里总结一下学到的知识,打一下Java基础,算是挖一个新坑。代码地址:源码地址第四章 Java常用类解析1. String,StringBuffer,StringBuilderString是一个final修饰的类,所有属性也是final的,所以String具有不可变性,也就是对字符串的操作,如拼接、剪切都会产生新的String对象。StringBuffer本质是一个线程安全(用synchronize修饰一些方法)的可修改字...

功利性得去找了下面试题库,发现一个讲面试题的教程,觉得讲得不错,教程地址
在这里总结一下学到的知识,打一下Java基础,算是挖一个新坑。
代码地址:源码地址
发现了个刷题的网站,题量大,有解析,暂未发现收费现象,社区氛围也不错,地址:网站地址
正在根据错题内容,逐渐重构完善本系列文章结构。

第四章 Java常用类解析

1. String,StringBuffer,StringBuilder

String是一个final修饰的类,所有属性也是final的,所以String具有不可变性,也就是对字符串的操作,如拼接、剪切都会产生新的String对象。
StringBuffer本质是一个线程安全(用synchronize修饰一些方法)的可修改字符串序列,因为保证线程安全,所有会带来额外的性能消耗。
StringBuilder本质上和StringBuffer没有区别,但是StringBuilder去掉了线程安全部分,提高了操作效率,是绝大部分情况下字符串拼接的首选。
如果确定拼接字符串会发生多次,并且长度可预计,那么可以在开始的时候指定合适的大小,避免数组扩容造成的开销。

1.1 String对象创建过程

例:下面代码创建了几个对象,输出是什么
String s1 = new String(“abc”);
String s2 = new String(“abc”);
System.out.println(s1 == s2);

答:String s1 = new String(“abc”);这里"abc"是静态文字池中的一个对象,new String()时,会将池中的对象复制一份到heap中,并把heap堆中的引用交给s1。
上述代码中,pool有一个对象,heap中有两个对象,s1,s2是引用,==比较的是内存地址,两个引用指向的是不同的地址,所以输出false。

2. HashMap和Hashtable

2.1 HashMap和Hashtable的区别

1)Hashtable继承自Dictionary,HashMap继承自AbstractMap,二者都实现了Map接口。
2)Hashtable不允许null key和null value,HashMap允许。
3)HashMap的使用几乎和Hashtable相同,不过H俺是table是synchronize同步的。

2.2 HashMap的put方法

java1.7版本:数据结构是链表+数组。在新元素插入,触发Map扩容的时候,会涉及到计算新元素在新Map中的位置,需要用到头插法(线程不安全)。多线程下可能会造成环形引用,进入死循环。
java1.8版本:数据结构是链表+数组+红黑树。
当一个链表的长度大于8的时候,put会进行红黑树的操作(如果总容量小于64先扩容)
当红黑树中元素个数小于6的时候,再从红黑树转回链表。
多线程进行put操作的时候,可能会出现数据被覆盖的情况。

3. ArrayList和LinkList

1)ArrayList底层是动态数组,LinkList底层是双链表
2)ArrayList添加元素和删除元素涉及到数组元素的移动,向指定位置添加/删除元素效率没有LinkList高
3)对于随机访问get和set,ArrayList优于LinkList

4. &和&&

都是与运算,a与b 全真得真,有假得假
&没有短路前后两个表达式都运行
&&有短路,第一个表达式false的时候就不运行第二个表达式了

5. final修饰符

final修饰值类型,变量一旦赋值就不能改变。
final修饰引用类型,被引用的对象属性值可以改变,但是该引用不能指向新的对象(不能new)。

6. ==和equals()

==:如果比较的对象是基本数据类型,则比较的是数值是否一致;如果比较的是引用数据类型,则比较的是对象的地址值是否一致。

equals():equals()方法不能用于比较基本数据类型的对象,如果对象和自身进行比较,则equals()方法与==是一样的(比较引用地址)。对于String类 Date类 File类等 可重写equals() 方法用于比较对象的属性内容是否一致(比较重写的逻辑指定的值)。
当Integer和int相比时,Integer会被拆箱,比较数值,Integer i3 =Integer.valueOf(59);前面有个Integer i1 = 59;所以i3引用i1。

7. include

静态的include:是jsp的指令来实现的,<% @ include file=“xx.html”%> 特点是 共享request请求域,先包含再编译,不检查包含页面的变化。不接受重名冲突。
动态的include:是jsp动作来实现的,<jsp:include page=“xx.jsp” flush=“true”/> 这个是不共享request请求域,先编译在包含,是要检查包含页面的变化的。可以重名。

8. Date

Date date=new Date();
System.out.printf("%tD%n",date);
tD 美国格式的日期 07/31/20月日年(2020/07/31)
tT 24小时时间 13:20:18 当前时间(时分秒)
tY 四位的年 2020 年份
助记:D(day月日年)T(time时分秒)Y(year年)

第五章 多线程

1. 实现方式

1.1 继承Thread类

首先新建一个类,继承Thread类,重写run方法,需要多线程执行该类的run方法时,new多个该类的实例,然后start方法。

1.2 实现Runnable接口

新建一个类,重写run方法(避免单继承的局限,适合多个线程处理同一资源的情况
需要多线程执行时先实例化刚新建的类,然后把实例作为参数新建Thread对象,并startnew Thread(runnable).start();
用同一个实例新建的Thread资源是共享的。

1.3 实现Callable接口

重写call方法,允许返回值抛出异常
新建部分和Runnable类似,只是在call方法中多了个返回值。调用部分:初始化一个实例:Callable<Integer> callable = new MyCallable();,用该实例新建FutureTask对象实例:FutureTask<Integer> task1 = new FutureTask<>(callable);用FutureTask实例创建线程实例并运行。new Thread(task1).start();返回值从FutureTask实例的get方法获取Integer num1 = task1.get();

1.4 使用线程池

减少创建新线程的时间,重复利用线程池中线程,降低资源消耗,可有返回值
关注线程的获取,可以将上面的线程类放到线程池里进一步限制线程的实现方式。
Executors.newFixedThreadPool方法,新建ExecutorService实例(线程池)
新建runnable,callable实例。用作线程池的submit方法的参数,可以直接运行这两个实例的多线程。
runnable 直接submit。
callable 也是直接submit,返回值是Future,可以用get方法获取callable的返回值。

2. 同步问题

2.1 synchronized和ReentrantLock

1)synchronized:可以用来同步方法和同步代码块。
同步方法:给一个方法增加synchronize关键字,可以是静态方法(锁住整个类)也可以是非静态方法(不能是抽象方法)
同步代码块:通过锁定一个指定的对象,来对同步代码块进行同步。
同步是高开销的操作,尽量少用同步方法,同步关键代码的代码块即可。
2)ReentrantLock:可重入锁,代码通过lock()方法获取锁,但必须调用unlock()方法释放锁。
注:当一个线程访问某对象的synchronized方法或者synchronized代码块时,其他线程对该对象的该synchronized方法或者synchronized代码块的访问将被阻塞。
当在对象上调用其任意synchronized方法的时候,对象都被加锁。
当一个线程访问某对象的synchronized方法或者synchronized代码块时,其他线程仍然可以访问该对象的非同步代码块。

2.2 sleep()和wait()

①sleep是线程类(Thread)的方法,wait是Object类的方法;
②sleep不释放对象锁,wait放弃对象锁
③sleep暂停线程、但监控状态仍然保持,结束后会自动恢复
④wait后进入等待锁定池,只有针对此对象发出notify或者notifyall方法(这里经常会漏一个)后获得对象锁进入就绪状态(这里经常会挖坑“运行状态”)
⑤两个方法都需要InterruptedException异常处理。
⑥wait()方法可以有参数,也可以无参数;sleep()方法必须要传入long的参数。

本文地址:https://blog.csdn.net/qq_41109942/article/details/107656716