面试题:2022年7月8日

问:1.Java中Runnable和Callable有什么不同

问:2.手写一个队列出来试试 要求:可以放入数据(放在队列后面),获取数据(第一个),查看数据(查看队列中的数据)

my code

问:3.Java内存模型是什么?

问:4.Java中的volatile 变量是什么?

问:5.索引失效

问:6.wait/sleep的区别

答:
1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。
sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

2.最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
sleep不让出系统资源;wait是进入线程等待池等待,让出系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
synchronized(x){
x.notify()
//或者wait()
}

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
总结
两者都可以暂停线程的执行。

对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。

Wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。

sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。

在调用sleep()方法的过程中,线程不会释放对象锁。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。线程不会自动苏醒。

问:java 中的 Math.round(-1.5) 等于多少?

答:
什么是Math.round()?
round()是Math类中的一个四舍五入的方法.Math类中对这个方法有重载,可以传入一个double类型的参数返回的是一个long类型的数值,也可以传入一个float类型的参数返回的是一个int类型的数值.

计算规则
源码实现中使用了一些位运算,round()方法中调用了一些使用native修饰的方法,需要使用工具.
计算规则,就是round()方法在实现四舍五入的时候实际上是不论正负的,它会先将这个数加上0.5然后在像下取整.

结果
-1.5+0.5=-1.0,然后-1.0向下取整结果为-1,最后的结果就是-1
问题的点就是计算规则中的+0.5,如果将-1.5换成+1.5的话结果就是
1.5+0.5=2.0,然后2.0向下取整结果为2

问:String str="i"与 String str=new String(“i”)一样吗?

答:
不一样
因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String(“i”)方式,则会被分到堆内存中。
String str1 = “i”;
String str2 = “i”;
String str3 = new String(“i”);
System.out.println(str1 == str2);//ture
System.out.println(str2 == str3);//false
解释:

String str=“i” Java 虚拟机会将其分配到常量池中:常量池不会重复创建对象。
在String str1="i"中,把i值存在常量池,地址赋给str1。假设再写一个String str2=“i”,则会把i的地址赋给str2,但是i对象不会重新创建,他们引用的是同一个地址值,共享同一个i内存。

String str=new String(“i”) 分到堆内存中:堆内存会创建新的对象。
假设再写一个String str3=new String(“i”),则会创建一个新的i对象,然后将新对象的地址值赋给str3。虽然str3和str1的值相同但是地址值不同。

拓展:
堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。

问:抽象类必须要有抽象方法吗?修饰吗?

问:抽象类能使用 final 么
答:
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类。
抽象类的就是要子类继承然后实现内部方法的。但是final修饰的类是不能再被继承和修改的。所以不能用final修饰。