互联网Java工程师面试题·Java 面试篇·第一弹

目录

volatile%20%E6%95%B0%E7%BB%84%E5%90%97%EF%BC%9F-toc" style="margin-left:40px;">1、Java 中能创建 volatile 数组吗?

volatile%20%E8%83%BD%E4%BD%BF%E5%BE%97%E4%B8%80%E4%B8%AA%E9%9D%9E%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E5%8F%98%E6%88%90%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E5%90%97%EF%BC%9F-toc" style="margin-left:40px;">2、volatile 能使得一个非原子操作变成原子操作吗?

volatile%20%E4%BF%AE%E9%A5%B0%E7%AC%A6%E7%9A%84%E6%9C%89%E8%BF%87%E4%BB%80%E4%B9%88%E5%AE%9E%E8%B7%B5%EF%BC%9F-toc" style="margin-left:40px;">3、volatile 修饰符的有过什么实践?

volatile%20%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E6%8F%90%E4%BE%9B%E4%BB%80%E4%B9%88%E4%BF%9D%E8%AF%81%EF%BC%9F-toc" style="margin-left:40px;">4、volatile 类型变量提供什么保证?

5、10 个线程和 2 个线程的同步代码,哪个更容易写?

6、你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

7、什么是多线程环境下的伪共享(false sharing)?

8、什么是 Busy spin?我们为什么要使用它?

9、Java 中怎么获取一份线程 dump 文件?

10、Swing 是线程安全的?

11、什么是线程局部变量?

12、用 wait-notify 写一段代码来解决生产者-消费者问题?

13、用 Java 写一个线程安全的单例模式(Singleton)?

14、Java 中 sleep 方法和 wait 方法的区别?


volatile%20%E6%95%B0%E7%BB%84%E5%90%97%EF%BC%9F">1、Java 中能创建 volatile 数组吗?

        能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。


volatile%20%E8%83%BD%E4%BD%BF%E5%BE%97%E4%B8%80%E4%B8%AA%E9%9D%9E%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E5%8F%98%E6%88%90%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E5%90%97%EF%BC%9F">2、volatile 能使得一个非原子操作变成原子操作吗?

        一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或 double 变量的读写是原子。


volatile%20%E4%BF%AE%E9%A5%B0%E7%AC%A6%E7%9A%84%E6%9C%89%E8%BF%87%E4%BB%80%E4%B9%88%E5%AE%9E%E8%B7%B5%EF%BC%9F">3、volatile 修饰符的有过什么实践?

        一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是 64 位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write barrier),读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。


volatile%20%E7%B1%BB%E5%9E%8B%E5%8F%98%E9%87%8F%E6%8F%90%E4%BE%9B%E4%BB%80%E4%B9%88%E4%BF%9D%E8%AF%81%EF%BC%9F">4、volatile 类型变量提供什么保证?

        volatile 变量提供顺序和可见性保证,例如,JVM 或者 JIT 为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和long 就是原子的。


5、10 个线程和 2 个线程的同步代码,哪个更容易写?

        从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互独立的。但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。


6、你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:

// The standard idiom for using the wait method
synchronized (obj) {
while (condition does not hold)
obj.wait(); // (Releases lock, and reacquires on wakeup)
... // Perform action appropriate to condition
}


7、什么是多线程环境下的伪共享(false sharing)?

        伪共享是多线程系统(每个处理器有自己的局部缓存)中一个众所周知的性能问题。伪共享发生在不同处理器的上的线程对变量的修改依赖于相同的缓存行,伪共享问题很难被发现,因为线程可能访问完全不同的全局变量,内存中却碰巧在很相近的位置上。如其他诸多的并发问题,避免伪共享的最基本方式是仔细审查代码,根据缓存行来调整你的数据结构。


8、什么是 Busy spin?我们为什么要使用它?

Busy spin 是一种在不释放 CPU 的基础上等待事件的技术。它经常用于避免丢失 CPU 缓存中的数据(如果线程先暂停,之后在其他 CPU 上运行就会丢失)。所以,如果你的工作要求低延迟,并且你的线程目前没有任何顺序,这样你就可以通过循环检测队列中的新消息来代替调用 sleep() 或 wait() 方法。它唯一的好处就是你只需等待很短的时间,如几微秒或几纳秒。LMAX 分布式框架是一个高性能线程间通信的库,该库有一个 BusySpinWaitStrategy 类就是基于这个概念实现的,使用 busy spin 循环 EventProcessors 等待屏障


9、Java 中怎么获取一份线程 dump 文件?

在 Linux 下,你可以通过命令 kill -3 PID (Java 进程的进程 ID)来获取 Java应用的 dump 文件。在 Windows 下,你可以按下 Ctrl + Break 来获取。这样 JVM 就会将线程的 dump 文件打印到标准输出或错误文件中,它可能打印在控制台或者日志文件中,具体位置依赖应用的配置。如果你使用 Tomcat。


10、Swing 是线程安全的?

不是,Swing 不是线程安全的。你不能通过任何线程来更新 Swing 组件,如JTable、JList 或 JPanel,事实上,它们只能通过 GUI 或 AWT 线程来更新。这就是为什么 Swing 提供 invokeAndWait() 和 invokeLater() 方法来获取其他线程的 GUI 更新请求。这些方法将更新请求放入 AWT 的线程队列中,可以一直等待,也可以通过异步更新直接返回结果。你也可以在参考答案中查看和学习到更详细的内容。


11、什么是线程局部变量?

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。


12、用 wait-notify 写一段代码来解决生产者-消费者问题?

http://java67.blogspot.sg/2012/12/producer-consumer-problem-with-wait-and-notify-example.html

请参考答案中的示例代码。只要记住在同步块中调用 wait() 和 notify()方法,如果阻塞,通过循环来测试等待条件。


13、用 Java 写一个线程安全的单例模式(Singleton)?

http://javarevisited.blogspot.in/2012/12/how-to-create-thread-safe-singleton-in-java-example.html

请参考答案中的示例代码,这里面一步一步教你创建一个线程安全的 Java 单例类。当我们说线程安全时,意思是即使初始化是在多线程环境中,仍然能保证单个实例。Java 中,使用枚举作为单例类是最简单的方式来创建线程安全单例模式的方式。


14、Java 中 sleep 方法和 wait 方法的区别?

虽然两者都是用来暂停当前运行的线程,但是 sleep() 实际上只是短暂停顿,因为它不会释放锁,而 wait() 意味着条件等待,这就是为什么该方法要释放锁,因为只有这样,其他等待的线程才能在满足条件时获取到该锁。


要想了解更多:

千题千解·Java面试宝典_时光の尘的博客-CSDN博客


http://www.niftyadmin.cn/n/5108605.html

相关文章

软考高项-规划风险应对

规划风险应对是为处理整体项目风险敞口,以及应对单个项目风险,而制定可选方案、选择应对策略并商定应对行动的过程。 本过程的主要作用是,制定应对整体项目风险和单个项目风险的方法,本过程还将分配资源,并根据需要将相…

一百九十二、Flume——Flume数据流监控工具Ganglia单机版安装

一、目的 在安装好Flume之后,需要用一个工具可以对Flume数据传输进行实时监控,这就是Ganglia 二、Ganglia介绍 Ganglia 由 gmond、gmetad 和 gweb 三部分组成。 (一)第一部分——gmond gmond(Ganglia Monitoring Da…

【Java】正则表达式,校验数据格式的合法性。

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ 正则表达式 正则表达式: ①可以校…

SpringCloud 微服务全栈体系(二)

第三章 Eureka 注册中心 假如我们的服务提供者 user-service 部署了多个实例,如图: 思考几个问题: order-service 在发起远程调用的时候,该如何得知 user-service 实例的 ip 地址和端口?有多个 user-service 实例地址…

SQL union all的使用

背景: 公司业务开发需要将两个取出两个相同表结构(原料、辅料)的数据,组成一个新视图,使用了UNION ALL SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GOCREATE view vw_rawmaterial_ny_list as ( select id,ccode,cc…

Nginx负载均衡反向代理动静分离

文章目录 nginx负载均衡&反向代理&动静分离环境说明部署动静分离1.主机lnmp部署一个动态页面,在此以discuz论坛系统为例2.主机n1部署两个静态页面访问动、静态页面 配置负载均衡配置反向代理访问测试 nginx负载均衡&反向代理&动静分离 环境 主机名…

SystemVerilog Assertions应用指南 Chapter1.38在序列匹配时调用子程序

SVA可以在序列每次成功匹配时调用子程序。同一序列中定义的局部变量可以作为参数传给这些子程序。对于序列的每次匹配,子程序调用的执行与它们在序列定义中的顺序相同。 module sub;logic a, b, clk;initial $vcdpluson();initial begin clk 1b0; a1b0; b1b0; repeat(2) (pos…

主机重启后k8s kubelet无法自动启动问题解决梳理

1.问题描述 OS Version:CentOS Linux release 7.9.2009 (Core) K8S Version:Kubernetes v1.20.4 K8S安装配置完成后,重启服务器发现,kubelet没有正常启动(systemctl status kubelet) 命令: systemctl status kubelet [root@centos79-3 ~]# systemctl status kubelet ●…