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

功利性得去找了下面试题库,发现一个讲面试题的教程,觉得讲得不错,教程地址
在这里总结一下学到的知识,打一下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. &和&&

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

3. final修饰符

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

4. ==和equals()

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

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

5. include

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

6. 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的参数。

3. 共享与隔离

线程共享 ①代码段 ②数据段 ③打开文件列表 ④堆
线程私有 ①线程id ②寄存器 (用于暂时存放数据)③工作栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值