专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java学习 企业Java面试题,50道精选Java线程题

企业Java面试题,50道精选Java线程题

更新时间:2019-08-26 13:51:31 来源:动力节点 浏览1988次

  1)什么是线程?


  线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。Java在语言层面对多线程提供了卓越的支持,它也是一个很好的卖点。


  2)线程和进程有什么区别?


  线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。


  3)如何在Java中实现线程?


  在语言层面有两种方式。java.lang.Thread类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承java.lang.Thread类或者直接调用Runnable接口来重写run()方法实现线程。


  4)用Runnable还是Thread?


  这个问题是上题的后续,大家都知道我们可以通过继承Thread类或者调用Runnable接口来实现线程,问题是,哪个方法更好呢?什么情况下使用它?这个问题很容易回答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类,当然是调用Runnable接口好了。


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


  这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。


  7)Java中Runnable和Callable有什么不同?


  Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。


  8)Java中CyclicBarrier和CountDownLatch有什么不同?


  CyclicBarrier和CountDownLatch都可以用来让一组线程等待其它线程。与CyclicBarrier不同的是,CountdownLatch不能重新使用。


  9)Java内存模型是什么?


  Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。这个关系定义了一些规则让程序员在并发编程时思路更清晰。比如,先行发生关系确保了:


  线程内的代码能够按先后顺序执行,这被称为程序次序规则。


  对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。


  前一个对volatile的写操作在后一个volatile的读操作之前,也叫volatile变量规则。


  一个线程内的任何操作必需在这个线程的start()调用之后,也叫作线程启动规则。


  一个线程的所有操作都会在线程终止之前,线程终止规则。


  一个对象的终结操作必需在这个对象构造完成之后,也叫对象终结规则。


  可传递性


  我强烈建议大家阅读《Java并发编程实践》第十六章来加深对Java内存模型的理解。


  10)Java中的volatile变量是什么?


  volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生,就是上一题的volatile变量规则。


  11)什么是线程安全?Vector是一个线程安全类吗?


  如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector是用同步方法来实现线程安全的,而和它相似的ArrayList不是线程安全的。


  12)Java中什么是竞态条件?举个例子说明。


  竞态条件会导致程序在并发情况下出现一些bugs。多线程对一些资源的竞争的时候就会产生竞态条件,如果首先要执行的程序竞争失败排到后面执行了,那么整个程序就会出现一些不确定的bugs。这种bugs很难发现而且会重复出现,因为线程间的随机竞争。一个例子就是无序处理


  13)Java中如何停止一个线程?


  Java提供了很丰富的API但没有为停止线程提供API。JDK1.0本来有一些像stop(),suspend()和resume()的控制方法但是由于潜在的死锁威胁因此在后续的JDK版本中他们被弃用了,之后JavaAPI的设计者就没有提供一个兼容且线程安全的方法来停止一个线程。当run()或者call()方法执行完的时候线程会自动结束,如果要手动结束一个线程,你可以用volatile布尔变量来退出run()方法的循环或者是取消任务来中断线程。


  14)如何避免死锁?

image.png

  Java多线程中的死锁死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:


  互斥条件:一个资源每次只能被一个进程使用。


  请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。


  不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。


  循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。


  避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。


  15)如何强制启动一个线程?


  这个问题就像是如何强制进行Java垃圾回收,目前还没有觉得方法,虽然你可以使用System.gc()来进行垃圾回收,但是不保证能成功。在Java里面没有办法强制启动一个线程,它是被线程调度器控制着且Java没有公布相关的API。


提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>