Java并发编程73道面试题及答案 —— 面试稳了 (7)

线程组和线程池是两个不同的概念,他们的作用完全不同,前者是为了方便线程的管理,后者是为了管理线程的生命周期,复用线程,减少创建销毁线程的开销。

26、为什么使用Executor框架比使用应用创建和管理线程好?

为什么要使用Executor线程池框架

每次执行任务创建线程 new Thread()比较消耗性能,创建一个线程是比较耗时、耗资源的。

调用 new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制的创建,线程之间的相互竞争会导致过多占用系统资源而导致系统瘫痪,还有线程之间的频繁交替也会消耗很多系统资源。

直接使用new Thread() 启动的线程不利于扩展,比如定时执行、定期执行、定时定期执行、线程中断等都不便实现。

使用Executor线程池框架的优点

能复用已存在并空闲的线程从而减少线程对象的创建从而减少了消亡线程的开销。

可有效控制最大并发线程数,提高系统资源使用率,同时避免过多资源竞争。

框架中已经有定时、定期、单线程、并发数控制等功能。

综上所述使用线程池框架Executor能更好的管理线程、提供系统资源使用率。

27、java中有几种方法可以实现一个线程?

继承 Thread 类

实现 Runnable 接口

实现 Callable 接口,需要实现的是 call() 方法

28、如何停止一个正在运行的线程?

使用共享变量的方式 在这种方式中,之所以引入共享变量,是因为该变量可以被多个执行相同任务的线程用来作为是否中断的信号,通知中断线程的执行。

使用interrupt方法终止线程 如果一个线程由于等待某些事件的发生而被阻塞,又该怎样停止该线程呢?这种情况经常会发生,比如当一个线程由于需要等候键盘输入而被阻塞,或者调用Thread.join()方法,或者Thread.sleep()方法,在网络中调用ServerSocket.accept()方法,或者调用了DatagramSocket.receive()方法时,都有可能导致线程阻塞,使线程处于处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这里我们给出的建议是,不要使用stop()方法,而是使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态,退出堵塞代码。

29、notify()和notifyAll()有什么区别?

当一个线程进入wait之后,就必须等其他线程notify/notifyall,使用notifyall,可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个。

如果没把握,建议notifyAll,防止notigy因为信号丢失而造成程序异常。

30、什么是Daemon线程?它有什么意义?

所谓后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。

反过来说, 只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。注意:后台进程在不执行finally子句的情况下就会终止其run()方法。

比如:JVM的垃圾回收线程就是Daemon线程,Finalizer也是守护线程。

31、java如何实现多线程之间的通讯和协作?

中断和共享变量

32、什么是可重入锁(ReentrantLock)?

举例来说明锁的可重入性

public class UnReentrant{ Lock lock = new Lock(); public void outer(){ lock.lock(); inner(); lock.unlock(); } public void inner(){ lock.lock(); //do something lock.unlock(); } } outer中调用了inner,outer先锁住了lock,这样inner就不能再获取lock。其实调用outer的线程已经获取了lock锁,但是不能在inner中重复利用已经获取的锁资源,这种锁即称之为 不可重入可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。

synchronized、ReentrantLock都是可重入的锁,可重入锁相对来说简化了并发编程的开发。

33、当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?

如果其他方法没有synchronized的话,其他线程是可以进入的。

所以要开放一个线程安全的对象时,得保证每个方法都是线程安全的。

34、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwzsxy.html