Java求职面试中那些棘手的线程问题
【威哥说】昨天的文章发出后,好多同学告诉我说自己现在就是处在一个迷茫的时期,找不到方向。不用着急,你肯定可以找到属于自己的种子,也许和我一样是Java,也许是其他。你需要立刻做的就是去扪心自问,是自己兴趣,还是高薪的工作,抑或是你仅仅需要磨砺营作为平台。今天在这里和大家聊一聊在Java求职中经常被问到的关于线程的问题。
一、现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
答:可以使用join方法实现,join:表示等其他线程,他有一个时间参数,也可以不设置时间参数。当没有的时候,表示等这个线程执行完再往下执行,当有参数时,假设现在主线程为mainThread,支线程为aThread,bThread;mainThread里执行aThread.join(10000) ;表示mainThread等aThread执行10秒再说。但如果10秒里,aThread最多只要执行5秒就完事,那么,mainThread只要等5秒就会不再等了。因为aThread已经完事了。如果10秒里aThread要10秒以上的时间才能执行完。那会怎样呢?mainThread会不管你执行完没完,等你10秒就不等了。哥先走一步。
二、在Java中Lock比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它?
答:lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Java线程面试的问题越来越会根据面试者的回答来提问。我强烈建议在你去参加多线程的面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。
三、在java中wait和sleep方法的不同?
答:通常会在电话面试中经常被问到的Java线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。
四、用Java写代码来解决生产者——消费者问题。
与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在Java中怎么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的方法。有些时候他们甚至会问怎么实现哲学家进餐问题。
五、如何预防死锁
死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。“synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性的访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁。 所以我们要在使用同步的时候去关心它,避免发生。
六、为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?
线程的运行不是像其他方法那么简单的额调用一下就运行的。想要运行一个线程,肯定是要和操作系统打交道,告诉操作系统我要添加一个线程,run方法只是个简单的方法,里面就是你要运行的代码。start方法里面会调用一个native方法,这个方法才是真正和操作系统交流的
七、Java中你怎样唤醒一个阻塞的线程?
这是个关于线程和阻塞的棘手的问题,它有很多解决方法。如果线程遇到了IO阻塞,我并且不认为有一种方法可以中止线程。如果线程因为调用wait()、sleep()、或者join()方法而导致的阻塞,你可以中断线程,并且通过抛出InterruptedException来唤醒它。