目录

15道问答题

7道选择题


先给大家复习一下基础题!!!

Java基础是java初学者的起点,是帮助你从小白入门到精通必学基础课程!

22道多线程面试题问答+选择题_对象锁22道多线程面试题问答+选择题_java面试题_02

 为初学者而著!

Java300集>>>适合准备入行开发的零基础员学习Java,基于最新JDK13、IDEA平台讲解的,视频中穿插多个实战项目。每一个知识点都讲解的通俗易懂,由浅入深。不仅适用于零基础的初学者,有经验的程序员也可做巩固学习。

 配套学习:Java初学者入门教程>>>

 

15道问答题

1. 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?

这个线程面试题通常在第一轮面试或电话面试时被问到,这道多线程问题为了测试面试者是否熟悉 join 方法的概念。答案也非常简单——可以用 Thread 类的 join 方法实现这一效果。

 

2. Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。

多线程和并发编程中使用 lock 接口的最大优势是它为读和写提供两个单独的锁,可以让你构建高性能数据结构,比如 ConcurrentHashMap 和条件阻塞。

这道 Java 线程面试题越来越多见,而且随后的面试题都基于面试者对这道题的回答。

我强烈建议在任何 Java 多线程面试前都要多看看有关锁的知识,因为如今电子交易系统的客户端和数据交互中,锁被频繁使用来构建缓存。

 

3. Java 中 wait 和 sleep 方法有什么区别?

我们来看看另一个经常被问到的线程面试题。这道题常出现在电话面试中。两者主要的区别就是等待释放锁和监视器。sleep方法在等待时不会释放任何锁或监视器。wait 方法多用于线程间通信,而 sleep 只是在执行时暂停。可以看我另一篇有关Java 中 wait 和 sleep的文章。

 

4. 如何在 Java 中实现一个阻塞队列?

这是一道相对困难的 Java 多线程面试题,考察点很多。它考察了面试者是否真正写过 Java 多线程代码,考察了面试者对并发场景的理解。并且可以根据面试者的代码问很多后续问题,如果他用 wait() 和 notify() 方法成功实现了阻塞队列,可以让他用 Java 5 的并发类重新实现一次。

 

5. 如何在 Java 中编写代码解决生产者消费者问题?答案

和上面有关线程的问题相似,这个问题在工作中很典型,但有时面试官会问这类问题,比如“在 Java 中如何解决生产者消费者问题?”其实,有很多解决方式。我分享过用 Java 中 BlockingQueue 的解决方案。有时他们甚至会让你给出哲学家进餐问题的解决方案。

 

6. 写一段死锁代码。你在 Java 中如何解决死锁?

这是我最喜欢的 Java 多线程面试题,因为即使死锁在多线程并发编程中十分常见,许多面试者仍然抓耳挠腮,不能写出无死锁的代码。

只需要问他们如果有 N 个资源和 N 个线程去执行某个操作,然后请求所有资源。

这里的 N 可以是 2 作为最简单的情况,也可以是个很大的数字让问题变复杂。有关死锁的更多信息可以看这篇文章Java 中如何避免死锁。

 

7. 什么是原子操作?Java 中有哪些原子操作?

这是个简单的 Java 线程面试题。另一个紧随其后的问题将是:你需要同步原子操作吗?你可以看这篇文章了解更多Java 同步。

 

8. Java 中 volatile 关键字是什么?你如何使用它?它和 Java 中的同步方法有什么区别?

自从 Java 5 中调整 volatile 关键字和 Java 内存模型后,有关 volatile 关键字的线程问题越来越常见。掌握 volatile变量在并发环境中如何确保可见性、有序性和一致性非常重要。

 

9. 什么是竞态条件?你如何发现并解决竞态条件?

这个 Java 多线程问题一般出现在高级面试。多数面试官会问你最近一次遇到的竞态条件,如何解决的,有时他们也会写点简单代码让你发现竞态条件。可以看看我的这篇文章Java 中的竞态条件。我认为,这是最棒的 Java 线程面试问题之一,而且可以测试出面试者解决竞态条件的经验,或是编写无数据竞争、无其竞态条件的代码经验。

 

10. 在 Java 中你如何转储线程(thread dump)?如何分析它?

在 UNIX 中,你可以使用 kill -3 然后线程转储日志会打印在屏幕上,可以使用 CTRL+Break 查看。这只是一个较简单的线程面试题,狡猾一点的话他们会问你如何分析转储日志。线程转储日志对于分析死锁情况非常有用。

 

11. 既然 start() 方法会调用 run() 方法,为什么我们调用 start() 方法,而不直接调用 run() 方法?

这是一个基本的 Java 多线程面试题。最初,我刚开始多线程编程时对此还有些困惑。如今我一般在 Java 中级面试的电话面试或一轮面试中遇到。

这道问题的答案是这样的。当你调用 start() 方法时,它会新建一个线程然后执行 run() 方法中的代码。如果直接调用 run() 方法,并不会创建新线程,方法中的代码会在当前调用者的线程中执行。可以看这篇文章了解更多线程中 Start 和 Run 方法的区别。

 

12. Java 中你如何唤醒阻塞线程?

这是有关线程的一个很狡猾的问题。有很多原因会导致阻塞,如果是 IO 阻塞,我认为没有方式可以中断线程(如果有的话请告诉我)。另一方面,如果线程阻塞是由于调用了 wait(),sleep() 或 join() 方法,你可以中断线程,通过抛出 InterruptedException 异常来唤醒该线程。可以看这篇文章了解有关处理阻塞线程的知识Java 中如何处理阻塞方法。

 

13. Java 中 CyclicBarriar 和 CountdownLatch 有什么区别?

最近的 Java 线程面试题多数在测试你对 JDK 5 并发包的掌握程度。两者区别之一就是 CyclicBarrier 在屏障打开之后(所有线程到达屏障点),可以重复使用。而 CountDownLatch 不行。想了解更多可以参与课程Java 中的多线程和并行计算。

 

14. 什么是不可变类?它对于编写并发应用有何帮助?

尽管这道面试题和线程没有直接关系,但间接影响也很大。如果面试官随后让你写一个不可变类,或问你为什么 Java 中的 String 是不可变的,会让面试题变得更加复杂。

 

15. 你在多线程环境中遇到的最多的问题是什么?你如何解决的?

内存干扰、竞态条件、死锁、活锁、线程饥饿是多线程和并发编程中比较有代表性的问题。这类问题无休无止,而且难于定位和调试。

 

7道选择题

1.下面程序的运行结果()(选择一项)

public static void main(String[] args) {

Thread t=new Thread(){

public void run(){

pong();

}

};

t.run();

System.out.println("ping");

}

static void pong(){

System.out.println("pong");

}
22道多线程面试题问答+选择题_java面试题_02

A. pingpong

B. pongping

C. pingpong和pongping都有可能

D. 都不输出

答案:B

分析:启动线程需要调用start()方法,而t.run()方法,则是使用对象名.分析:启动线程需要调用start()方法,而t.run()方法,则是使用对象名.

 

2.下列哪个方法可用于创建一个可运行的类()

A. public class X implements Runnable{public void run() {……}}

B. public class X extends Thread{public void run() {……}}

C. public class X extends Thread{public int run() {……}}

D. public class X implements Runnable{protected void run() {……}}

答案:AB

分析: 继承Thread和实现Runable接口

 

3.在Java多线程中,请用下面哪种方式不会使线程进入阻塞状态()

A. sleep()

B. Suspend()

C. wait()

D. yield()

答案:D

分析:yield会是线程进入就绪状态

 

4.关于sleep()和wait(),以下描述错误的一项是()

A. sleep是线程类(Thread)的方法,wait是Object类的方法

B. Sleep不释放对象锁,wait放弃对象锁

C. Sleep暂停线程、但监控状态任然保持,结束后会自动恢复

D. Wait后进入等待锁定池,只针对此对象发出notify方法后获取对象锁进入运行状态。

答案:D

分析:针对此对象的notify方法后获取对象锁并进入就绪状态,而不是运行状态。另外针对此对象的notifyAll方法后也可能获取对象锁并进入就绪状态,而不是运行状态

 

5.以下锁机机制中,不能保证线程安全的是()

A. Lock

B. Synchronized

C. Volatile

答案:C

 

6.下面所述步骤中,是创建进程做必须的步骤是()

A. 由调度程序为进程分配CPU

B. 建立一个进程控制块

C. 为进程分配内存

D. 为进程分配文件描述符

答案:BC

 

7.无锁化编程有哪些常见方法?()

A. 针对计数器,可以使用原子加

B. 只有一个生产者和一个消费者,那么就可以做到免锁访问环形缓冲区(Ring Buffer)

C. RCU(Read-Copy-Update),新旧副本切换机制,对于旧副本可以采用延迟释放的做法

D. CAS(Compare-and-Swap),如无锁栈,无锁队列等待

答案:D

分析:A 这方法虽然不太好,但是常见

B ProducerConsumerQueue就是这个,到处都是

C linux kernel里面大量使用

D 本质上其实就是乐观锁,操作起来很困难。。单生产者多消费者或者多生产者单消费者的情况下比较常见,也不容易遇到ABA问题。

 小伙伴如果想要学习更多的知识,学习材料可以,工众号:编程领域

Java初学者学习教程:Java初学者入门教程>

22道多线程面试题问答+选择题_java面试题_02