首页 > 编程语言 >Java面试题5

Java面试题5

时间:2023-11-02 18:34:36浏览次数:37  
标签:面试题 Java 对象 ThreadLocal 线程 内存 key 守护

Java面试题(第五天)

1.对线程安全的理解

不是线程安全,应该是内存安全,堆是共享内存,可以被所有线程访问

当多个线程访问一个对象时,如果不用进行额外的同步控制或其他协调操作,调用这个对象的行为都可以获得正确的结果,我们就说这个对象时线程安全的

是进程和线程共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间,堆在操作系统堆进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是用完了要还给操作系统,要不然就是内存泄漏。

在Java中,堆是Java虚拟机所管理的内存中最大的一块,是所有线程共享的一块内存区域,在虚拟机启动时创建,堆所存在的内存区域的唯一目的就是存放对象实例,几乎所有的对象实例和数组都会在这里分配。

是每个线程独有的,保存其运行状态和局部自动变量的,栈在线程开始的时候初始化,每个线程的栈相互独立。因此,栈是线程安全的,操作系统在切换线程的时候会自动切换栈,栈空间不需要再高级语言里面显式的分配和释放

目前主流操作系统都是多任务的,即多个线程同时进行,为了保证安全,每个线程只能访问分配给自己的内存空间,而不能访问别的进程的,这是有操作系统保障的。

在每个进程的内存空间都会有一个特殊的公共区域,通常称为堆(内存),进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。

2.守护线程的理解

守护线程:为所有非守护线程提供服务的线程,任何一个守护线程都是整个JVM所有非守护线程的保姆;

守护线程类似于整个进程中的一个默默无闻的小喽啰:它的生死无关重要,它却依赖于整个进程而运行;哪天其他线程技术了,没有要执行的了,程序就结束了吗,理都没理守护线程,就把它中断了;

注意:由于守护线程的终止是自身无法控制的,因此千万不要把IO、File等重要操作逻辑分配给它,因为它不靠谱;

守护线程的作用是什么?

举例,GC垃圾回收线程:就是一个经典的守护线程,当我们的程序中不再有人任何运行的Thread程序就不会再产生垃圾,垃圾回收期就无事可做,所以当垃圾回收线程是JVM上仅剩的线程时,垃圾回收线程会自动离开,它始终在低级别的状态中运行,用于实时监控和管理体统中的可回收资源。

应用场景:(1)来为其他现场提供服务支持的情况;(2)或者在任何情况下,程序结束时,这个线程必须正常且立刻关闭,就可以作为守护线程来使用;反之,如果一个正在执行某个操作的线程必须要正确地关闭掉否则就会出现不好的后果的话,那么这个线程就不能是守护线程,而是用户线程,通常都是些关键的实物,比方说,数据库录入或者更新,这些操作都是不能中断的。

thread setDaemon(true)必须在thread.start()之间设置,否则会抛出一个IllegalTheadStartException异常,你不能把正在运行的常规线程设置为守护线程。

在Daemon线程中产生的新线程也是Daemon的。

守护线程不能用于去访问固有的资源,比如读写操作或者计算逻辑,因为他会在任何时候甚至一个操作的中间发生中断。

Java自带的多线程框架,比如ExecutorService,会将守护线程转为用户线程,所以如果要使用后台线程就不能用Java的线程池。

3.ThreadLocal的原理和使用场景

每一个Thread对象均含有一个ThreadLocalMap类型的成员变量threadLocal;它储存本线程中所有ThreadLocal对象及其对应的值

ThreadLocalMap由一个个Entry对象构成

Entry继承自WeakReference<ThreadLocal<?>>,一个Entry由ThreadLocal对象和Object构成,由此可见,Entry的key是ThreadLocal对象,并且是一个弱引用。当没有指向key的强引用后,该key就会被垃圾收集器回收

当执行set方法是,ThreadLocal首先会获取当前线程对象,然后获取当前线程的ThreadLocalMap对象。再以当前ThreadLocal对象为key,将值存储进ThreadLocalMap对象中。

get方法执行过程类似,ThreadLocal首先会获取当前线程对象,然后获取当前线程ThreadLocalMap对象。再以当前ThreadLocal对象为key,获取对应的value。

由于每一条线程均含有各自私有的ThreadLocal容器,这些容器互相独立互不影响,因此不会存在线程安全性问题,从而也无需使用同步机制来保证多条线程访问容器的互斥性。

使用场景:
1.在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束

2.线程间数据隔离

3.进行事务操作,用于存储线程事务信息

4.数据库连接,Session会话管理。

Spirng框架在事务开始时会给我们当前线程绑定一个JDBC Connection,在整个事务过程都是使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架里面就是用户的ThreadLocal来实现这种隔离。

4.ThreadLocal内存泄漏原因,如何避免

内存泄漏为程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早会被占光。

不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄漏

强引用:使用最普遍的引用(new),一个对象具有很强的引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。

如果想取消强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。

弱引用:JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象,在Java中,用java.lang.ref.WeakReferemce类来表示。可以在缓存中使用弱引用。

ThreadLocal实现原理,每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例。value为线程变量的副本

image-20230911171007527

ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,key(ThreadLocal)势必会被GC回收,这样就导致ThreadLocalMap中key为null,而value还存在着强引用,只有Thread线程退出以后,value的强引用料条才会断掉,但如果当前

5.并发,并行,串行的区别

串行在时间上不可能发生重叠,前一个任务没搞定,下一个任务就只能等待

并行在时间上是可重叠的,两个任务在同一时刻互不干扰的同时执行

并发允许两个任务彼此干扰。统一时间点,只有一个任务运行,交替执行。

标签:面试题,Java,对象,ThreadLocal,线程,内存,key,守护
From: https://www.cnblogs.com/qisui/p/17806012.html

相关文章

  • Java面试题1
    Java面试题(第一天)1.JDK、JRE、JVM三者区别和联系区别:JDK:JavaDevelopmentKit(Java开发环境)JRE:JavaRuntimeEnvironment(Java运行环境)JVM:JavaVirtualMachine(Java虚拟机)联系:.java文件被javac编译成.class文件然后被jvm使用lib类库编译为机器码然后通过jvm映射到操......
  • Java-并发编程-进阶篇
    在上一篇幅中对并发编程进行了简单介绍:并发与并行,进程与线程,以及并发编程的简单代码但是在企业中往往并不能解决实际问题,例如:1.synchronized关键字在企业开发中会大大降低系统的性能2.当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象......
  • Java数组_03数组执行原理
    1、运行主要用到的三个区: 2、执行原理: ......
  • 学习:javaweb-servlet
    1.在Idea中配置maven仓库,需要在idea中的setting设置maven的路径参数,包括maven的setting.xml和本地仓库的路径2.新建一个maven模板的javaweb项目,查看maven的配置setting.xml是否配置成功,成功的话可以下载模板所需要的一依赖包。3.查看projectStructure中的Modules项目中是否生成......
  • React面试题: 我是否可以在项目中不断使用React.Component来优化项目
    React.PureComponent是React的一个组件,主要用于性能优化,可以避免不必要的渲染。它的主要特点是:如果组件的props和state没有发生变化,则不会重新渲染(此处原理类似React.memo)。可以自动检查对象和数组,判断其是否需要重新渲染(是浅比较)。但是,React.PureComponent的缺点......
  • java笔记_14_邮箱发送
    JavaMailSender:默认使用配置文件中的发送人邮箱密码等JavaMailSenderImpl:方法中使用Impl对象,可手动设置发送账户密码application.ymlspring:#spring集成配置(省略创建session过程)mail:host:#邮件服务器地址port:#邮件服务器端口proto......
  • 面试题: 前端处理滚动穿透这个顽疾
    诚如你所知:滚动穿透是指在移动端滑动页面的过程中,页面滚动受到了触摸事件的干扰,导致无法流畅地滚动,这主要是由于事件冒泡造成的。解决方法如下:监听touchmove事件,阻止默认行为监听touchmove事件,阻止事件的默认行为,防止事件冒泡到父元素上。禁止滚动可以通过over......
  • React面试题: useCallBack()与React.memo的区别与使用常见场景
    React.usecallback与React.memo的区别:React.useCallback和React.memo是两种不同的优化方式:主要功能:它们都可以避免不必要的渲染,提高React应用的性能。React.useCallback是Hoc(高阶组件)的解决方案,可以用于优化函数组件和Class组件,注意这里适用于React高阶组件的渲染解......
  • OFD添加图片水印-JAVA
    写出了一个ofd文件加图片水印的工具类,分享给大家参考。1、引入ofdrw<!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>provided</scope></depende......
  • 掌握JavaScript中数组遍历的7种方法
    作为JavaScript开发人员,熟悉数组的遍历和操作是非常重要的。数组遍历是处理和操作数组元素的基本需求之一。本文将介绍JavaScript中的10种常见数组遍历方法,帮助你成为数组操作的达人。数组的遍历for循环forEach方法for...of循环map方法reduce方法for...in循环filter方法for循环or循......