Java并发和线程面试问题答案
多线程是Java编程语言的一个重要特征,这意味着线程也是任何Java面试的一个重要组成部分。这是真的,事实上,在初学者和应届生,Java中的水平线程面试问题是最难回答的问题之一。与多线程和并发有关的面试题之所以难,一个原因是对多个线程如何协同工作感到困惑,另一个原因是线程确实是一个复杂的话题,需要正确理解和使用。
大多数线程面试题都是检查Java程序员在Java线程API、Java并发API方面的知识,以及与多线程有关的问题,如竞赛条件、线程安全和死锁。
有些时候,多线程和并发性的面试问题也关注并行设计模式,如解决生产者-消费者问题,实现工作偷取模式,或解决Java中的用餐哲学家问题。这在面试有4到6年经验的Java开发人员时尤其如此。
在这篇文章中,我们将看看在各种面试中提出的 不同类型的多线程和并发问题 ,如电话或面对面的面试,书面测试,有经验的和高级的Java开发人员,以及一些正确回答的技巧。
在电话面试或第一轮面试中提出的问题往往比较简单,你必须用面试官所期望的关键词来回答。在面对面的面试中,要为不同类型的后续问题做好准备。
12个Java线程并发面试问题及答案
正如我所说,在这篇Java文章中,不仅如此,我还将分享一些应届生和初学者最常问的线程面试问题,如2到4年的工作经验,以及一些正确回答的技巧和窍门。
顺便说一下,这些线程面试问题对高级Java开发人员或有一些Java经验的人同样有用。我已经尝试在主题上分享这些面试问题的答案,但我建议你做一些研究,好好学习这个主题,以回答任何后续问题,这是因为你对这些Java主题问题的回应。
1.Java线程中的启动和运行方法有什么区别? (答案)
这个线程面试问题也被问到,如果start()方法最终调用了run()方法,那么为什么要调用start()方法,为什么不直接调用run()方法。好吧,原因是,因为start方法创建了一个新的线程,在新线程上调用run方法里面写的代码,而调用run方法是在同一个线程上执行这些代码。你也可以参见文章start vs run method in Java来了解更多细节。
2.编写代码以避免Java中N个线程访问N个共享资源的死锁? (答案)
这是一个经典的Java多线程面试问题,几乎出现在每一个Java线程问题列表中。这个问题是基于没有适当同步或不正确同步的并行程序所面临的风险和问题。
这个问题探讨了寻找的概念和获取和释放共享资源的锁的最佳做法。顺便说一下,这在很多地方也有涉及,我建议阅读《如何防止Java中的死锁》,不仅是为了详细回答这个Java多线程问题,也是为了学习如何防止Java中的死锁。
3.在Java中实现线程,扩展线程类和实现Runnable哪个更好? (答案)
好吧,这又是一个在任何Java线程面试中经常问到的问题。从本质上讲,在Java中实现线程有两种方法,通过扩展java.lang.Thread类或实现java.lang.Runnable接口。
通过扩展类,你是在利用你的机会来扩展一个任何只有一个的类,因为Java不支持多重继承,通过实现Runnable接口,你仍然可以扩展另一个类。所以扩展Runnable甚至Callable是一个更好的选择。你也可以看看《Java中的Runnable与Thread类》,了解这些问题的更多答案。
鉴于其简单性和基于事实的性质,这个问题大多出现在电话面试或初步筛选中。在回答这个问题时,需要提到的关键点包括在类的层面上的多种继承,以及定义一个任务和执行一个任务的分离。Runnable只代表一个任务,而Thread则同时代表任务和任务的执行。
4.什么是Busy Spinning?为什么要用Busy Spinning作为一种等待策略? (答案)
这是Java中高级的并发性面试问题之一,只问有经验的高级Java开发人员,他们有大量的并发性编码经验。顺便说一下,忙转的概念并不新鲜,但它在多核处理器中的使用最近有所上升。
忙碌等待是一种等待策略,即一个线程等待一个条件为真,但不是调用等待或睡眠方法并释放CPU,而是直接旋转。如果条件很快就会成真,即在一毫秒或一微秒内,这就特别有用。
不释放CPU的好处是,所有的缓存数据和指令都不会受到影响,如果这个线程在一个核心上被暂停,并被带回另一个线程,这些数据和指令可能会丢失。如果你能回答这个问题,那就可以放心了,这是个好印象。
5.Java中的CountDownLatch 和CyclicBarrier 有什么区别?(答案)
Java中的 CountDownLatch 和CyclicBarrier 是Java 5 Concurrency API中增加的两个重要的并发工具。两者都是用来实现一个线程在开始处理之前必须等待另一个线程的场景,但它们之间是有区别的。
在回答这个问题的时候,需要提到的关键点是,CountDownLatch在计数达到零后是不能重用的,而CyclicBarrier在障碍被打破后也可以重用。
你也可以看看我之前的文章《Java中CyclicBarrier和CountDownLatch的区别》,了解对这个并发性面试问题的更详细的回答,以及在现实生活中使用这些并发性工具的例子。
6.Java中的wait和sleep有什么区别? (方法)
还有一个来自电话面试的经典Java多线程问题。在回答这个问题时,需要提到的关键点是,wait会释放锁,而且必须从同步上下文中调用,而sleep只会让线程暂停一段时间,并保留锁。
顺便说一下,这两个方法都会抛出IntrupptedException ,并且可以被打断,这可能会导致一些后续问题,例如,我们可以在Java中唤醒一个正在睡觉或等待的线程吗?你也可以在我的同名帖子中看到详细的答案。
7.如何解决Java中的生产者-消费者问题?( 解决方案)
在任何Java多线程面试中,我最喜欢的问题之一,几乎一半的并发问题都可以归类为生产者-消费者模式。在Java中,基本上有两种方法来解决这个问题,一种是使用等待和通知方法,另一种是使用Java中的BlockingQueue 。如果你在Java 5中编写代码,后者很容易实现,是一个不错的选择。
在回答这个问题时,需要提到的关键点是BlockingQueue的线程安全 和阻塞性,以及在编写并发代码时如何帮助。
你还可以期待很多后续问题,包括:如果你有多个生产者线程或多个消费者,会发生什么,如果一个生产者比消费者线程快,或者反过来,会发生什么。你也可以看看这个链接,了解如何在Java中使用阻塞队列来编码生产者-消费者设计的例子。
8.为什么Java中ConcurrentHashMap比Hashtable快? (答案)
ConcurrentHashMap 是在Java 5中作为Hashtable的替代品被引入的,它的速度更快,因为它的设计。ConcurrentHashMap将整个地图分为不同的段,在更新操作中只锁定一个特定的段,而不是Hashtable,后者锁定整个地图。
ConcurrentHashMap 还提供了无锁读取,这在Hashtable中是不可能的,因为这一点和锁的剥离,ConcurrentHashMap比Hashtable快,特别是当读取者的数量多于写入者的数量时。
为了更好地回答这个流行的Java并发性面试问题,我建议阅读我关于Java中ConcurrentHashMap的内部工作的文章。
9.Java中Executor和ExecutorService的submit()和execute()方法有什么区别?(答案)
来自ExecutorService 接口的提交和执行方法之间的主要区别是,前者以Future对象的形式返回结果,而后者不返回结果。顺便说一下,两者都是用来向Java中的线程池提交任务的,但一个是在Executor 接口中定义的,而另一个是添加到ExecutorService 接口中的。这个多线程面试问题在第一轮的Java面试中也会被问到。
10.在Java中如何在两个线程之间共享数据?(答案)
再来看看电话面试中的一个Java多线程问题。你可以通过使用共享对象或共享数据结构(如队列)在线程之间共享数据。根据你所使用的东西,你需要提供线程安全保证,而提供线程安全的一种方式是使用同步关键字。
如果你使用Java 5中的并发集合类,例如BlockingQueue,你可以很容易地共享数据,而不必为线程安全和线程间通信而烦恼。我喜欢这个线程问题,因为它的简单性和有效性。这也引出了进一步的后续问题,即由于线程间共享数据而产生的问题,例如竞赛条件。
11.什么是Java中的ReentrantLock?你以前使用过它吗?(答案)
ReentrantLock是Java中同步关键字的替代品,它的引入是为了处理同步关键字的一些限制。Java 5中的许多并发工具类和并发集合类,包括ConcurrentHashMap ,都使用了ReentrantLock,以利用优化。
ReentrantLock大多使用原子变量和更快的CAS操作来提供更好的性能。需要提到的关键点是ReentrantLock和Java中的synchronized关键字之间的区别,其中包括可以中断地获取锁,在等待锁的时候有超时功能等。
12.什么是Java中的ReadWriteLock?在Java中使用ReadWriteLock有什么好处?(答案)
这通常是以前的Java并发问题的后续问题。 ReadWriteLock 又是基于锁剥离的概念,这是高级线程安全机制之一,主张将读写操作的锁分开(详见Heinz Kabutz的Java Concurrency in Practice Bundle)。
如果你以前注意到,如果没有写者,读操作可以不加锁,这可以极大地提高任何应用程序的性能。ReadWriteLock 利用了这个想法,并提供了允许最大并发水平的策略。Java并发API也提供了这个概念的实现,即ReentrantReadWriteLock。
根据面试官和应聘者的经验,你甚至可以期待提供你自己的ReadWriteLock的实现,所以也要做好准备。
这里有一张很好的图,清楚地解释了Java中读写锁的工作原理。
这些是我最喜欢的一些 基于Java中多线程和并发的面试问题。线程和并发是Java中的一个大话题,有很多有趣的、棘手的和艰难的问题,但对于初学者和新鲜人来说,这些问题肯定有助于清除Java中的任何线程面试。
感谢你到目前为止阅读这篇文章。如果你觉得这些Java并发和多线程面试问题有用,那么请与你的朋友和同事分享。如果您有任何问题或反馈,请留言。




