【2022持续更新】大数据最全知识点整理-Java篇

简介: 【2022持续更新】大数据最全知识点整理-Java篇

@TOC

语言特性

string,stringgbuffer,stringbuilder区别:

共同之处:

  • 三者共同之处:都是final类,不允许被继承

不同之处:

  • String:不可变字符串,初始化时可以赋空值,每次对String的操作都会生成一个新的String对象,效率较低且浪费大量内存空间。
  • StringBuffer:可变字符串、效率低、线程安全;StringBuffer对象默认生成16个字节的缓冲容量,当字符串大小超过容量时,会自动增加容量。
  • StringBuilder:可变字符序列、效率高、线程不安全;与StringBuffer一样都继承和实现了同样的接口和类,方法除了没使用synch修饰以外基本一致
深入阅读: String,StringBuffer与StringBuilder的区别??

== 和equals区别

对于理解==和equals的区别,我们首先需要了解Java中的基本数据类型与引用类型
基本数据类型: Byte,short,int,long,double,folat,boolean,char,这八种数据变量中直接存储值,无equals方法。
引用类型: 除以上基本类型之外的都是引用类型,像String类型属于引用类型,变量中存储的是引用地址,对应的地址中存储数据。
equals

  • 只有引用类型含有此方法,比较的是两个引用类型中的引用地址的值是否相同。

==

  • 对于基本类型:比较的就是基本类型的值是否相同。
  • 对于引用类型:比较的就是引用地址是否相同。
深入阅读: 浅谈Java中equals()和==的区别

ArrayList和LinkedList的区别

1.ArrayList是实现了基于动态数组的数据结构,采用下表索引对数据直接进行访问。每次对于新增或者删除非末尾的数据,都需要将后方的数据进行前移或后移操作。
LinkedList基于双链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

深入阅读 : ArrayList和linkedList的区别

HashTable和HashMap区别

  • HashTable:线程安全,不允许键值为null,效率稍低。继承自Dictonary类。
  • HashMap:线程不安全,允许键值为null,效率稍高。实现了Serializable接口支持序列化,实现了Cloneable接口能被克隆。继承自abstractMap。
深入阅读: HashMap和Hashtable的区别

并发与多线程

JAVA多线程实现的四种方式

  1. 继承Thread类
  2. 实现Runnable接口
  3. 使用ExecutorService、Callable、Future实现有返回结果的多线程。
  4. 通过线程池创建线程

前两种无返回值,通过重写run方法实现,run方式的返回值是void,所以没有办法返回结果。
后两种有返回值,通过Callable接口实现call方法,这个方法的返回值是Object,返回的结果可以放在Object对象中。

Thread 类中的start() 和 run() 方法有什么区别?

  • 通过start()方法来启动一个线程,此时线程处于就绪状态,可以被JVM来调度执行,在调度过程中,JVM通过调用线程类的run()方法来完成实际的业务逻辑,当run()方法结束后,此线程就会终止,所以通过start()方法可以达到多线程的目的。
  • 如果直接调用线程类的run()方法,会被当做一个普通的函数调用,程序中仍然只有主线程这一个线程,start()方法呢能够异步的调用run()方法,但是直接调用run()方法缺是同步的,无法达到多线程的目的。

volatile 和synchronized ?

volatile

  1. volatile不会造成线程的阻塞,是Java提供的一种轻量级锁,相比使用synchronized所带来的庞大开销,volatile效率更高。
  2. volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取
  3. volatile仅能实现变量的修改可见性,不能保证原子性;
  4. volatile仅能使用在变量级别

synchronized

  1. 通常称为重量级锁,锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. synchronized则可以使用在变量、方法、和类级别的
  3. 而synchronized则可以保证变量的修改可见性和原子性
深入阅读: Java并发编程:volatile关键字解析

什么是线程池? 为什么要使用它?

创建线程要花费昂贵的资源和时间,如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

而且一个进程能创建的线程数有限。为了避免这些问题,可以采用线程池的方式多多线程进行管理。并对线程进行复用,而不是执行完一个任务就进行销毁。

创建线程池一般是分为自动创建和手动创建,自动创建线程池的几种方式都封装在Executors工具类中,他是根据应用场景封装好了一些创建参数,但是实际使用中不推荐采用自动创建的方式,推荐使用ThreadPoolExecutor手动创建线程池:通过手动创建的方式确保使用者更加明确线程池的运行规则,避免线程池的资源耗尽。

ThreadPoolExecutor类是线程池中最核心的一个类,有7个构造参数

  1. corePoolSize:核心线程池的大小。指的是线程池中常驻的线程数,在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务。也可以调用prestartCoreThread()方法预创建线程。

当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;

  1. maximumPoolSize:线程池最大线程数,它表示在线程池中最多能创建多少个线程;
  2. keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用。

但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

  1. unit:参数keepAliveTime的时间单位,有七种属性,天、小时、分钟、秒、毫秒、微妙、纳秒
  2. workQueue:一个阻塞队列,用来存储等待执行的任务。
  3. threadFactory:线程工厂,主要用来创建线程;
  4. handler:表示当拒绝处理任务时的策略,

在ThreadPoolExecutor类中有几个非常重要的方法:

  • execute:通过这个方法可以向线程池提交一个任务,交由线程池去执行。
  • submit:也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,因为它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。
  • shutdown()和shutdownNow()是用来关闭线程池的。shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。
  • 而shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。
深入理解: Java并发编程:线程池的使用

JVM内存模型

JVM 运行时内存共分为程序计数器,Java虚拟机栈,本地方法栈,堆,方法区五个部分。
其中 Java虚拟机栈、本地方法栈、程序计数器是线程私有的。
在这里插入图片描述
1、程序计数器(线程私有): 一个指向方法区中的方法字节码指针,由执行引擎读取下一个将要执行的指令代码,是一个非常小的内存空间,几乎可以忽略不记,是唯一一个在Java虚拟机规范中没有OutOfMemoryError情况的区域。

jvm的多线程是通过线程轮流切换并分配处理器执行时间来实现的,在一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此每条线程都需要有一个独立的程序计数器标记当前处理的位置,各条线程之间计数器互不影响,是“线程私有”的内存。

如果正在执行的是Native方法,这个计数器则为空(undefined)。

2、Java虚拟机栈(线程私有): 生命周期和线程相同,在线程创建时创建,线程结束栈内存也就释放,所以对于栈来说不存在垃圾回收问题。基本类型的变量和对象的引用变量都是在当前内存中分配。每个方法在执行的同时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。方法从调用到完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

局部变量表所需的内存空间在编译期完成分配,在方法运行期间不会改变局部变量表的大小。

如果线程请求的栈深度大于虚拟机允许的深度,将会抛出Stack Overflow栈溢出异常;如果动态扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

3、本地方法栈(线程私有): 本地方法栈与虚拟机栈作用类似,虚拟机栈执行Java方法,本地方法栈执行native方法服务。native方法指的是在java中调用的其他编程语言的方法,融合不同的编程语言为Java所用

与虚拟机栈一样也会抛出Stack OverflowError异常和OutOfMemoryError异常。

4、Java堆(线程共享): JVM中最大的区域,几乎所有的实例对象和数据都是存在这个区域,被所有线程共享的,一个 JVM 实例只存在一个堆内存,堆内存的大小是可以调节的。也是 gc 主要的回收区。

堆内存分为3大部分:新生代、老年代和永久代,其中新生代又进一步划分为Eden、S0、S1(Survivor)三个区,在JDK1.8之后,堆的永久代取消了,由元空间取代。从内存回收角度看,现在收集器基本一般分代收集算法,可以更好的回收内存并且更快的分配内存。

我们创建的对象会优先在Eden分配,如果是大对象(很长的字符串数组)则可以直接进入老年代。另外,长期存活的对象将进入老年代,每一次MinorGC(年轻代GC),对象年龄就大一岁,默认15岁晋升到老年代,也可以手动设置晋升年龄。

如果Survivor空间中相同年龄所有对象的大小总和大于Survivor空间的一半,那么年龄大于等于该对象年龄的对象即可晋升到老年代
在这里插入图片描述
如果在堆中没有内存用来分配实例,并且堆也无法扩展,将会抛出OutOfMemoryError异常。

5、方法区(线程共享): 和堆一样所有线程共享,主要用于存储已经加载的类信息、常量、静态变量、和编译后的代码等数据。包括运行时常量池。

运行时常量池:作为方法区的一部分。用于存放编译期生成的各种字面量和符号引用,动态性,不要求常量一定只能在编译期产生,运行期间也可能产生新的常量,这些常量被放在运行时常量池中。

简述GC内存回收

大白话说就是垃圾回收机制,内存空间是有限的,你创建的每个对象和变量都会占据内存,java提供自动清除无用对象的功能,清除对象将内存释放出来,这就是GC要做的事。
堆是Java虚拟机进行垃圾回收的主要场所,其次要场所是方法区。

垃圾回收分为年轻代区域发生的Minor GC和老年代区域发生的Full GC

  • Minor GC(年轻代GC):

对象优先在Eden中分配,当Eden中没有足够空间时,虚拟机将发生一次Minor GC,因为Java大多数对象都是朝生夕灭,所以Minor GC非常频繁,而且速度也很快。

  • Full GC(老年代GC):

Full GC是指发生在老年代的GC,当老年代没有足够的空间时即发生Full GC,发生Full GC一般都会有一次Minor GC。

判断一个对象是否应该被回收,主要是看其是否还有引用。方法包括引用计数法以及可达性分析。

  • 引用计数法:

是一种比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只需要收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。

  • 可达性分析:

可达性分析的基本思路就是通过一系列可以做为root的对象作为起始点,从这些节点开始向下搜索。当一个对象到root节点没有任何引用链接时,则证明此对象是可以被回收的。

常见的回收算法有标记-清除算法,复制算法和标记整理算法。

类加载顺序

类加载过程即是指JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的过程。

JVM不是一开始就把所有的类都加载进内存中,而是只有第一次遇到某个需要运行的类时才会加载,且只加载一次。

加载分为五个步骤:
加载 -> 验证 -> 准备 -> 解析 -> 初始化。

加载: 把class字节码文件从各个来源通过类加载器装载入内存中,类加载器:一般包括引导类加载器,扩展类加载器,系统类加载器,以及用户的自定义类加载器。
验证: 确保加载进来的 calss 文件包含的额信息符合 Java 虚拟机的要求;
准备: 为类变量分配内存,设置类变量的初始值;
解析: 将常量池内的符号引用转为直接引用;
初始化: 初始化类变量和静态代码块。

new一个对象的具体过程

双亲委派机制

在当前类加载器接到加载类的请求时,首先将加载任务委托给父加载器,依次递归,如果父加载器可以完成类加载任务,就成功返回;如果父加载器无法完成此加载任务时,才会自己去加载。

其中类加载器分为以下四种:

  1. 引导类加载器:负责加载Java基础类
  2. 扩展类加载器:它负责加载JRE的扩展目录
  3. 系统类加载器:负责加载CLASSPATH变量所指定的目录下所有jar和class。
  4. 自定义类加载器。由Java实现。用户可以自定义类加载器,加载指定路径下的class文件。

优点:

  1. 避免重复加载。当双亲委派的过程中,如果父亲已经加载了该类,则当前类就不需要重新加载。
  2. 保证核心类不被篡改。通过委托方式,如果发现该类已经加载过之后,会直接返回已加载过的该类。确保核心类不会被篡改。即使类被篡改,因为不同的加载器加载同一个.class也不是同一个对象。这样也能保证核心类的执行安全。

还有哪些想看的面试题,读者可以在评论区补充,博主会在一天内进行更新。

相关实践学习
简单用户画像分析
本场景主要介绍基于海量日志数据进行简单用户画像分析为背景,如何通过使用DataWorks完成数据采集 、加工数据、配置数据质量监控和数据可视化展现等任务。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps 
目录
相关文章
|
17天前
|
JavaScript Java 编译器
Java包装类和泛型的知识点详解
Java包装类和泛型的知识点的深度理解
|
1月前
|
Java 程序员 编译器
Java继承与多态知识点详解
本文主要讲解的是Java中继承与多态的知识点
|
1月前
|
数据采集 分布式计算 大数据
Java语言在大数据处理中的应用
传统的大数据处理往往依赖于庞大的数据中心和高性能的服务器,然而随着大数据时代的到来,Java作为一种强大的编程语言正在被广泛应用于大数据处理领域。本文将探讨Java语言在大数据处理中的优势和应用,以及其在分布式计算、数据处理和系统集成等方面的重要作用。
|
10天前
|
设计模式 SQL Java
java基础知识点(初级二)
java基础知识点(初级二)
|
10天前
|
存储 Java 容器
java基础知识点(初级)
java基础知识点(初级)
|
22天前
|
Java
java线程知识点总结
Java线程核心概念:线程是程序执行流,一个进程可有多个线程。创建线程通过继承Thread或实现Runnable接口。线程状态包括新建、就绪、运行、阻塞、等待、超时等待和终止。同步用synchronized或Lock防止数据不一致,避免死锁。线程间通过共享变量、wait/notify通信。线程池(如ThreadPoolExecutor、ScheduledThreadPoolExecutor)优化性能和资源管理。
17 6
|
22天前
|
安全 前端开发 Java
Java Web开发知识点学习总结
Java Web开发涉及Java基础、Servlet、JSP、数据库操作(SQL+JDBC)、MVC设计模式、Spring框架、Hibernate ORM、Web服务(SOAP&RESTful)、安全认证(HTTP Basic/Digest/OAuth)及性能优化(缓存、异步、负载均衡)。
18 3
|
26天前
|
设计模式 安全 Java
Java基础知识点总结1
Java基础知识点总结
24 0
|
1月前
|
Java 索引
java知识点总结(二)
java知识点总结(二)
14 0
|
1月前
|
存储 Java 数据库
java基础的知识点(一)
java基础的知识点(一)
13 0