Java常见面试题

Java中为什么没有指针

  • 栈中的变量指向堆内存的变量
  • Java中所有的基本数据类型的传递都是值传递,除此之外,其他任何传递都是地址传递

static关键字

  • 作用:方便在没有创建对象的情况下调用
  • 特点:不能修饰局部变量,也可以通过对象来调用
  • 与非静态变量的区别 :
    • 静态变量被所有对象共享,仅一个副本,在类被加载时初始化,且初始化的顺序按照被定义的顺序
    • 非静态变量是对象所拥有的,存在多个副本,在创建对象的时候被初始化

string,stringgbuffer,stringbuilder区别

\ string stringbuffer stringbuilder
是否可变 不可
效率
线程安全 安全 安全 不安全
是否可空值

final,finally,finalize区别

  • final:声明属性、方法和类时,表示属性不可变、方法不可被覆盖、类不可被继承
  • finally:异常处理语句结构中总是被执行的一部分
  • finalize:在垃圾回收机制中,回收此前未回收的内存垃圾,所有object都继承了

== 和equals区别

  • ==的作用:基本类型时比较的是值是否相同,引用类型时比较地址是否相同
  • equals的作用:在新类中覆盖了equals方法时,比较的是地址中的值;否则比较的是地址

HashTable 和 HashMap区别

\ 线程安全 允许有null的健和值 效率 方法是否synchronize
hashmap 不安全 不是
hashtable 安全 不是
    • hashset底层基于hashmap实现,元素不重复
    • 多线程下,hashmap进行put操作会引起死循环,CPU利用率100%
    • ConcurrentHashMap,JDK8之后,采用了 CAS + synchronized 来保证并发安全性。
    • Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。
\ 线程安全 初始空间 增长空间
vector 安全 可设置 2倍且可设置
ArrayList 不安全 可设置 1.5且不可设置

volatile的作用

  • 多个线程对该变量的内存可见性
  • 禁止指令重排序

volatile和synchronized的区别

\ 变量可见性 原子性 阻塞 指令重排序 仅当前线程访问
volatile 禁止
synchronized 不禁止

synchronized与lock的区别

\ 存在层次 锁释放 锁状态 锁类型 性能
synchronized jvm层面 线程执行完成或异常则释放 无法判断 可重入 少量同步
lock 一个类 finally中必须释放 可判断 可重入 大量同步
  • 可重入锁:某线程已经获得锁,可以再次获得该锁而不会发生死锁。synchronized和ReentrantLock都是可重入的,其中使用 ReentrantLock的时候一定要手动释放锁
  • 两者均是独占锁,是一种给悲观锁

sleep() 与 wait() 与 yield() 的区别

  • sleep() 线程进入阻塞状态,wait() 线程被挂起
  • 前者会让出CPU,但是不会释放同步资源;wait两个都会让出
  • yield不释放锁,进入可执行状态

并发的问题

  • 为什么并发不一定快?(上下文切换)
  • 线程有哪些分类?(守护线程、用户线程
  • 使用多线程的方法?(Thread、Runnable、ExecutorService
  • 缓存一致性问题?
    • 当程序在运行过程中,会将运算需要的数据从主存复制一份到cup的高速缓存当中,那么cpu进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束后,再将高速缓存中的数据刷新到主存当中
  • 锁的几种状态:无锁->偏向锁→轻量锁→重量锁
  • CAS是什么?
    • 比较并交换。包含三个参数,内存位置、预期原值、新值。如果内存位置的原值与预期相同,则替换成新值;否则,就不替换
  • 重排序的分类:编译器重排序、指令级重排序、内存级重排序
  • 为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
    • new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
\ 优点 缺点 适用场景
偏向锁 加锁解锁无需额外消耗 竞争线程多时会带来额外消耗 基本没有线程竞争
轻量级锁 线程竞争不会阻塞,使用自旋 如果一直不能获取锁,长时间的自旋造成CPU消耗 少量进程竞争锁
重量级锁 进程会阻塞,CPU不会空转消耗CPU 线程阻塞 大量进程竞争CPU

锁总结

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章