JAVA常考面试题

  • 目录

    JDK和JRE的区别

    值传递和引用传递

    线程和进程的区别

    线程状态

    同步方法和同步代码块的区别

    死锁:

    避免死锁的方法

    Iterator和ListIterator的区别

    快速失败和安全失败

    HashMap的工作原理

    ArrayList和Array的区别:

    arraylist和linkedlist的区别

    Comparable和Comparator接口的区别:

    优先级队列


    JDK和JRE的区别

    • Java运行时环境(JRE)。它包括Java虚拟机、Java核心类库和支持文件。它不包含开发工具(JDK)--编译器、调试器和其他工具。

    • Java开发工具包(JDK)是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者开发、编译、执行Java应用程序。

  • 值传递和引用传递

    • 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量.

      引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。

      一般认为,java内的基础类型数据传递都是值传递. java中实例对象的传递是引用传递

  • 线程和进程的区别

    • a.地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

    • b.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

    • c.调度和切换:线程上下文切换比进程上下文切换要快得多。

    • d.在多线程OS中,进程不是一个可执行的实体。

  • 线程状态

    • 1. 新建( new ):新创建了一个线程对象。

    • 2. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取 cpu 的使用权 。

    • 3. 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。

    • 4. 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。阻塞的情况分三种:

      (一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。

      (二). 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁 被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。

      (三). 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。            当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。

    • 5. 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。

  •  
  • 同步方法和同步代码块的区别

    • 同步方法默认用this或者当前类class对象作为锁;

      同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;

      同步方法使用关键字 synchronized修饰方法,而同步代码块主要是修饰需要进行同步的代码,用   synchronized(object){代码内容}进行修饰;

  • 死锁:

    • 所谓死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。死锁产生的4个必要条件:

    • 互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
    • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
    • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
    • 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。
  • 避免死锁的方法

    • 顺序加锁:所有线程按照相同的顺序获得锁
    • 限时加锁:尝试获取锁的时候加一个限时时间,超时则放弃请求锁
    • 死锁检测:当一个线程请求失败,这个线程可以遍历锁的关系图时都有死锁发生,检测得到可以放弃所有锁
  • Iterator和ListIterator的区别

    • Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
      Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
      ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
  • 快速失败和安全失败

    • 快速失败:使用迭代器遍历集合对象的时候,如果遍历过程中对集合对象进行了修改,则会抛出Concurrent Modification Exception
    • 原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用了modCount变量,如果集合在遍历中发生了改变,那么modCount就会变化,在下次迭代中,就会检测modCount是否是expectedmodCount的值,是的话继续,否则抛出异常,注意,如果修改了modCount满足modCount = expectedmodCount就不会异常,因此modCount!=expectedmodCount 这个条件才是异常发生的原因。
    • 场景::java.util 包下的集合类都是快速失败的,不能在多线程下发生并发修改
    • 安全失败:采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集
      合上进行遍历
    • 原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,
      所以不会触发 Concurrent Modification Exception
    • 缺点:基于拷贝内容的优点是避免了 Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后
      的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的
    • 场景:java.util.concurrent 包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
  • HashMap的工作原理

    • 以key-value的形式存储元素,使用一个hash函数,使用hashcode()和equals()方法向集合添加和检索元素,使用put的时候,计算key的值,然后把value存储在合适的索引上,如果key存在,则替换;一些特性包括容量capacity,负载因子loadFactor,扩容threshold
  • ArrayList和Array的区别:

    • array可以包含基本类型和对象类型,arraylist只可以包含对象类型
    • array大小固定,arraylist的大小动态变化的
    • arraylist提供了更多的方法和特性
  • arraylist和linkedlist的区别

    • arraylist结构是数组,以O(1)的时间复杂度访问数据,但是插入删除需要移动元素,linkedlist是链表,查询速度为O(n),但是插入修改都是更快的O(1),
    • linkedList因为每个节点存储了两个引用,前和后,所以更加占内存
  • Comparable和Comparator接口的区别:

    • Comparable:只包含compareTo()方法,具体来说,返回复数,0,正数来表示已经存在的对象小于,等于,大于输入对象
    • Comparator:包含compare()和equals(),方法同上,equals()用来决定输入参数是否和comparator相等,只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true
  • 优先级队列

    • PriorityQueue保证每次取出的元素都是队列中权值最小的,元素的大小的评判可以通过元素本身的自然顺序,也可以通过构造时传入的比较器
    • ,线程不安全,出队列入队列都是O(logn),不允许放入null,通过完全二叉树实现的小顶堆
    • 添加元素的堆化过程
    • 移除元素的堆化过程

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 什么是线程线程与进程的区别是什么? 线程是进程的一部分,是CPU调度的最小单位,它可以并发执行。进程是操作系统资源分配的最小单位,它是程序的一次执行过程,包括了程序计数器、栈、数据段等多个内存区域。线程共享进程的内存空间,而进程之间是相互独立的。 2. 线程的状态有哪些?分别表示什么? 线程的状态包括:新建状态、就绪状态、运行状态、阻塞状态和死亡状态。 - 新建状态:线程创建后,尚未启动时的状态。 - 就绪状态:线程已经创建,并已经调用了 start() 方法,但还没有被分配到 CPU 执行。 - 运行状态:线程正在 CPU 上执行。 - 阻塞状态:线程由于某种原因暂时停止执行,直到唤醒才能转为就绪状态。 - 死亡状态:线程执行完 run() 方法后进入此状态。 3. 线程的实现方式有哪些?分别有什么优缺点? 线程的实现方式包括继承 Thread 类和实现 Runnable 接口两种方式。 - 继承 Thread 类的优点是编写简单,缺点是不能再继承其他类。 - 实现 Runnable 接口的优点是可以继承其他类,缺点是编写稍微麻烦一些。 4. 线程同步的方法有哪些?分别有什么优缺点? 线程同步的方法有 synchronized 关键字、Lock 接口、volatile 关键字等。 - synchronized 关键字的优点是简单易用,缺点是在竞争激烈的情况下会造成性能问题。 - Lock 接口的优点是可以更细粒度地控制同步,缺点是使用稍微复杂一些。 - volatile 关键字的优点是简单易用,缺点是只能保证可见性,不能保证原子性。 5. 什么是线程池?它的好处是什么? 线程池是一种管理和重用线程的机制。在创建一个线程的代价比较高的情况下,使用线程池可以避免频繁地创建和销毁线程,提高程序的性能。线程池的好处包括减少线程创建和销毁的开销、可控制并发线程数、能够提供更好的响应速度、提高线程的复用性等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值