Day1备战字节跳动面试

1.重载与重写的区别

  重载发生在同一个类中,访问修饰符,返回类型,参数名,参数个数,参数类型,参数顺序,不能完全相同,但是方法名必须相同。

  重写发生在不同类中, 存在于继承的关系中,访问修饰符大于父类,如果父类访问修饰符用private修饰,此方法不可被重写,返回类型小于父类,方法名相同,抛出异常小于父类,参数列表必须相同。

2.String  StringBufferStringBuilder 的区别是什么?String 为什么是不可变的?

  string类中使用final 关键字修饰字符数组来保存字符串,private final value [] ;所以string对象是不可变的。string类不可以被继承,因为该类被final修饰。

  而StringBuilder StringBuffer 都继承自 AbstractStringBuilder 类, AbstractStringBuilder 中也是使用字符数组保存字符串 char[]value  但是没有用 final 关键字修饰,所以这两种对象都是可变的。StringBuilder StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的。

  String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder StringBuilder 与StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

  每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。

StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用

StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

对三者使用的总结

  1.少量数据使用string

  2.单线程操作字符串缓冲区下操作大量数据使用stringBuilder

  3.多线程操作字符串缓冲区下操作大量数据使用stringBuffer

3. final 和static的区别

  final

    1.修饰类,这个类不能被继承

    2.修饰方法,这个方法不能被重写

    3.修饰变量,变量值一旦被赋值,不能被修改

  static

    1.修饰类方法,此方法被称为类方法,直接被类对象调用

    2.修饰代码块,在加载类的时候被执行

    3.修饰变量,JVM会为此变量在内存堆上分配空间,所有程序对它的引用指向这个内存空间,而不会重新分配空间。

  

4.同步代码块同步方法和同步锁

一 同步代码块

1.为了解决并发操作可能引起的异常,Java多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块。其语法如下:

synchronized(obj){

//同步代码块
}

其中obj就是同步监视器,他的含义是:线程开始执行同步代码块之前,必须获得同步监视器的锁定,任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定。虽然java程序允许使用任何对象作为同步监视器,但 是同步监视器的目的就是为了阻止两个线程对同一个共享资源进行并发访问,因此通常推荐使用可能被并发访问的共享资源充当同步监视器。

二 同步方法

同步方法就是使用synchronized关键字修饰某个方法,这个方法就是同步方法。这个同步方法(非static方法)无须显式指定同步监视器,同步方法的同步监视器是this,也就是调用该方法的对象。通过同步方法可以非常方便的实现线程安全的类,线程安全的类有如下特征:每个线程调用该对象的任意方法之后都能得到正确的结果;

每个线程调用该对象的任意方法之后,该对象状态依然能保持合理状态。
三 释放同步监视器的锁定

1,同步代码块,同步方法执行结束,当前线程即释放同步监视器;

2.当前线程在同步代码块、同步方法中遇到break,return终止了该代码块、方法的继续执行;

3.当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致了该代码块、方法的异常结束;

2.以下几种情况,线程不会释放同步监视器:

2.以下几种情况,线程不会释放同步监视器:

线程执行同步代码块或同步方法时,程序调用Thread.sleep(),Thread.yield()方法来暂停当前线程的执行,当前线程不会释放同步监视器;
线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放同步监视器,当然,程序应尽量避免使用suspend()和resume()方法来控制线程。
四 同步锁:
1.Java5开始,Java提供了一种功能更加强大的线程同步机制——通过显式定义同步锁对象来实现同步,这里的同步锁由Lock对象充当。
Lock 对象提供了比synchronized方法和synchronized代码块更广泛的锁定操作,Lock是控制多个线程对共享资源进行访问的工具。通常, 锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应该先获得Lock对象。

4.简述synchronized与java.util.concurrent.jocks.lock的异同

lock是Java5以后引入的API

主要相同点,lock能完成synchronized所实现的所有功能:

主要不同点:synchronized是在JVM层面的是一个关键字。而lock是一个类

lock有比synchronized更精确的线程语意和更好的性能,而且不强制一定要获得锁:

Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

猜你喜欢

转载自www.cnblogs.com/zjh-123/p/11029092.html