每日10道Java面试题打卡—Java基础篇2

简介: HashTable中每一个方法都加了锁,所以他是线程安全的,但是由于每个方法都加了锁,所以效率比较低,目前用的比较少。

底层实现是什么?



1、HashTable中每一个方法都加了锁,所以他是线程安全的,但是由于每个方法都加了锁,所以效率比较低,目前用的比较少。


2、HashMap允许Key和Value为null,而HashTable不允许。


3、底层实现:数组+链表


4、jdk8开始链表高度到8、数组长度超过64,链表转为红黑树。


5、如果产生hash冲突,先进行equals比较,相同则取代该元素,不同,则判断链表高度插入链表,链表高度达到8,并且数组长度到64则转变为红黑树,长度低于64则将红黑树转为链表。


十二、ConcurrentHashMap原理,jdk7和jdk8版本的区别



ConcurrentHashMap和HashTable都是线程安全的,但是ConcurrentHashMap使用的是分段锁,所以效率比HashTable高。


1、jdk7:数据结构:ReentrantLock+Segment+HashEntry,一个Segment中包含一个HashEntry数组,每个HashEntry又是一个链表结构。


2、锁:Segment分段锁,Segment继承了ReentrantLock,锁定操作的Segment,其他的Segment不受影响,并发度为Segment个数,可以通过构造函数指定,数组扩容不会影响其他的segment


3、元素查询:二次hash,第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部。


4、get方法无需加锁,volatile保证


5、jdk8:数据结构:synchronized+CAS+Node+红黑树,Node的val和next都用volatile修饰,保证可见性,查找,替换,赋值操作都使用CAS


6、锁:锁链表的head节点,不影响其他元素的读写,锁力度更细,效率更高,扩容时,阻塞所有的读写操作、并发、扩容。


7、读操作无锁:Node的val和next使用volatile修饰,读写线程对该变量互相可见,数组用volatile修饰,保证扩容时被读线程感知。


十三、如何实现一个IOC容器



1、配置文件配置包扫描路径


2、递归包扫描获取.class文件


3、反射、确定需要交给IOC管理的类


4、对需要注入的类进行依赖注入


十四、什么是字节码?作用是什么



1、我们平时写完的代码是.java后缀的,我们通过编译成.class文件后就是字节码文件,字节码是java虚拟机可读的。


2、作用:java是将源码编译为.class文件,然后又通过虚拟机解释运行的,这样解决了传统解释性语言执行效率低的问题,同时又保证了解释型语言可移植的特点。


十五、Java类加载器有哪些



1、JDK自带有三个类加载器:bootstrap ClassLoader(引导类加载器)、ExtClassLoader(扩展类加载器)、AppClassLoader(应用类加载器)。


2、bootstrap ClassLoader是EctClassLoader的父类加载器,默认加载lib下的jar包。


3、ExtClassLoader是AppClassLoader的父类加载器,负责加载lib/ext文件夹下的jar包。


4、AppClassLoader是应用类加载器,负责加载classpath下的类文件。


十六、双亲委派模型



19.png


十七、Java中的异常有哪些



1、Java中的所有异常都来自顶级父类Throwable。


2、Throwable下有两个子类Exception和Error。


3、Error是程序无法处理的错误,一旦出现这个错误,则程序将被迫停止运行。


4、Exception不会导致程序停止,又分为两种,一个是RunTimeExcepion运行时异常,另一个是CheckedException检查异常。


5、RunTimeException常常发生在程序运行过程中,会导致程序当前线程执行失败,CheckedException常常发生在程序编译过程中,会导致编译不通过。


十八、GC如何判断对象可以被回收



1、引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。


2、可达性分析法:从GC Roots开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象时不可用的,那么虚拟机就判断是可回收对象。


3、GC Roots的对象有:


1》虚拟机栈中引用的对象(比如New User(),那么这个User就是GC Roots)


2》方法区中类静态属性引用的对象


3》方法区中常量引用的对象


4》本地方法栈中引用的对象


十九、线程的生命周期,线程有哪些状态



1、线程通常有五种状态,创建、就绪、运行、阻塞和死亡状态。


2、阻塞的情况又分为三种:


1》等待阻塞:运行的线程执行wait方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中,进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify或notifyAll方法才能被唤醒,wait是object类方法。


2》同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。


3》其他阻塞:运行的线程执行sleep或join方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态,当sleep状态超时、join等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。sleep是Thread类的方法。


3、新建状态(New):新创建了一个线程对象。


4、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start方法,该状态的线程位于可运行线程池中,变得可运行,等待获取cpu的使用权。


5、运行状态(Running):就绪状态的线程获取了cpu,执行程序代码。


6、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃cpu使用权,暂时停止运行,直到线程进入就绪状态,才有机会转到运行状态。


7、死亡状态(Dead):线程执行完了或者因异常退出了run方法,该线程结束生命周期。


二十、sleep()、wait()、join()、yield()的区别



1、锁池


所有需要竞争同步锁的线程都会放在锁池当中,比如当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当前面的线程释放同步锁后锁池中的线程去竞争同步锁,当某个线程得到后会进入就绪队列进行等待CPU资源分配。


2、等待池


当我们调用wait()方法后,线程会放到等待池当中,等待池的线程是不会去竞争同步锁,只用调用了notify()或notifyAll()后等待池的线程才会开始去竞争锁,notify()是随机从等待池选出一个线程放到锁池,而notifyAll()是将等待池的所有线程放到锁池当中。


3、sleep是Thread类的静态本地方法,wait则是Object类的本地方法。


4、sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中。


5、sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。


6、sleep一般用于当前线程休眠,或者轮询暂停操作,wait则多用于多线程之间的通信。


7、sleep会让出cpu执行时间且强制上下文切换,而wait则不一定,wait后可能还是有机会重新竞争到锁继续执行的。


8、yield()执行后线程直接进入就绪状态,马上释放了cpu的执行权,但是依然保留了cpu的执行资格,所以有可能cpu下次进行线程调度还会让这个线程获取执行权继续执行。


9、join()执行后线程进入阻塞状态,例如在线程B中调用线程A的join(),那线程B会进入到阻塞队列,直到线程A结束或中断线程。



相关文章
|
1月前
|
Java 程序员
Java社招面试中的高频考点:Callable、Future与FutureTask详解
大家好,我是小米。本文主要讲解Java多线程编程中的三个重要概念:Callable、Future和FutureTask。它们在实际开发中帮助我们更灵活、高效地处理多线程任务,尤其适合社招面试场景。通过 Callable 可以定义有返回值且可能抛出异常的任务;Future 用于获取任务结果并提供取消和检查状态的功能;FutureTask 则结合了两者的优势,既可执行任务又可获取结果。掌握这些知识不仅能提升你的编程能力,还能让你在面试中脱颖而出。文中结合实例详细介绍了这三个概念的使用方法及其区别与联系。希望对大家有所帮助!
183 60
|
13天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
72 14
|
16天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
48 13
|
1月前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
84 16
|
1月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
66 9
|
1月前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
71 12
|
1月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
56 1
|
1月前
|
监控 Dubbo Java
Java Dubbo 面试题
Java Dubbo相关基础面试题
|
1月前
|
SQL Java 数据库连接
Java MyBatis 面试题
Java MyBatis相关基础面试题
|
1月前
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题

热门文章

最新文章