多线程面试20题(带答案)

一、线程和进程的区别
    线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,
    一个进程能够由不少个线程组成,线程间共享进程的全部资源,每一个线程有本身的堆栈和局部变量。
    线程由CPU独立调度执行,在多CPU环境下就容许多个线程同时运行。一样多线程也能够实现并发操做,
    每一个请求分配一个线程来处理html

二、实现线程有哪几种方式?
    继承Thread类建立线程,实现Runnable接口建立线程,实现Callable接口经过FutureTask包装器来建立Thread线程,
    使用ExecutorService、Callable、Future实现有返回结果的线程java

三、线程有哪几种状态?它们之间如何流转的?算法

   (https://zhidao.baidu.com/question/1738160030660108547.html)
   Java中,每一个线程都需经历新生、就绪、运行、阻塞和死亡五种状态,线程重新生到死亡的状态变化称为生命周期。
    用new运算符和Thread类或其子类创建一个线程对象后,该线程就处于新生状态。数据库

        线程的生命周期,把图转化为文字就是: 
        一、线程经过new方法建立,调用start,线程进入就绪状态,等待系统的调度(时间片轮转调度)。
        当系统调度,进入运行状态。正常结束或者异常退出,进程进入死亡状态。
        二、处于运行状态的线程若遇到sleep,则线程进入睡眠状态,不会让出资源锁,sleep结束,
        线程转为就绪状态,等待系统从新调度。api

        三、处于运行状态的线程可能在等待io,也可能进入挂起状态。io完成,转为就绪状态。缓存

        四、处于运行状态的线程yield,线程转为就绪状态。(yield只让给权限比本身高的)安全

        五、处于运行状态的线程遇到wait,线程处于等待状态,须要notify()/notifyALL来唤醒线程,
        唤醒后的线程处于锁定状态,获取了“同步锁”,以后,线程才转为就绪状态。处于运行的线程synchronized,
        加上后 变成同步操做。处于锁定状态,获取了“同步锁”,以后,线程才转为就绪状态。多线程

四、线程中的start()和run()方法有什么区别?
    start()方法是线程类的方法,目的是开启线程
    run()方法是线程任务方法,目的是写线程里面要作的事.并发

五、怎么终止一个线程?如何优雅地终止线程?
    使用退出标识,使得线程正常退出,即当run方法完成后进程终止。
    使用stop强行中断线程(此方法为做废过时方法),不推荐使用,暴力终止,可能使一些清理性的工做得不到完成。还可能对   锁定的内容进行解锁,容易形成数据不一样步的问题。
    this.interrupted():测试当前线程是否已经中断(静态方法)。若是连续调用该方法,则第二次调用将返回false。在api文档中说明interrupted()方法具备清除状态的功能。执行后具备将状态标识清除为false的功能。
    this.isInterrupted():测试线程是否已经中断,可是不能清除状态标识。框架

六、ThreadLocal在多线程中扮演什么角色?
    为每个线程存一个本地变量.和多线程加锁比以空间换时间.

七、线程中的wait()和sleep()方法有什么区别?
    sleep()不释放资源,仍然占用线程时间片.该方法是Thread类的方法
    wait()释放资源,让出cpu使用权.该方法是Object类的方法
八、多线程同步有哪几种方法?
    一、同步方法
    即有synchronized关键字修饰的方法。 因为java的每一个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,须要得到内置锁,不然就处于阻塞状态。
    二、同步代码块
    即有synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。    
    三、使用特殊域变量(volatile)实现线程同步

        (1)volatile关键字为域变量的访问提供了一种免锁机制;

        (2)使用volatile修饰域至关于告诉虚拟机该域可能会被其余线程更新;

        (3)所以每次使用该域就要从新计算,而不是使用寄存器中的值;

        (4)volatile不会提供任何原子操做,它也不能用来修饰final类型的变量。    
        
        就是使用volatile修饰可能会被多个线程公用的变量,可能会出错的变量.
    四、使用重入锁实现线程同步

    在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和块具备相同的基本行为和语义,而且扩展了其能力。
    ReenreantLock类的经常使用方法有:
    ReentrantLock() :建立一个ReentrantLock实例
    lock() :得到锁
    unlock() :释放锁    
    若是synchronized关键字能知足用户的需求,就用synchronized,由于它能简化代码 。若是须要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,不然会出现死锁,一般在finally代码释放锁。
    五、使用局部变量实现线程同步    
    若是使用ThreadLocal管理变量,则每个使用该变量的线程都得到该变量的副本,副本之间相互独立,这样每个线程均可以随意修改本身的变量副本,而不会对其余线程产生影响。
    
    ThreadLocal与同步机制
    a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题;
    b.前者采用以”空间换时间”的方法,后者采用以”时间换空间”的方式。
        
九、什么是死锁?如何避免死锁?
    线程死锁是指因为两个或者多个线程互相持有对方所须要的资源,致使这些线程处于等待状态,没法前往执行。
        固然死锁的产生是必需要知足一些特定条件的: 
            1.互斥条件:进程对于所分配到的资源具备排它性,即一个资源只能被一个进程占用,直到被该进程释放 
            2.请求和保持条件:一个进程因请求被占用资源而发生阻塞时,对已得到的资源保持不放。 
            3.不剥夺条件:任何一个资源在没被该进程释放以前,任何其余进程都没法对他剥夺占用 
            4.循环等待条件:当发生死锁时,所等待的进程一定会造成一个环路(相似于死循环),形成永久阻塞。
         处理死锁的基本方法
        1.预防死锁:经过设置一些限制条件,去破坏产生死锁的必要条件
        2.避免死锁:在资源分配过程当中,使用某种方法避免系统进入不安全的状态,从而避免发生死锁
        3.检测死锁:容许死锁的发生,可是经过系统的检测以后,采起一些措施,将死锁清除掉
        4.解除死锁:该方法与检测死锁配合使用

十、多线程之间如何进行通讯?
        wait()、notify()、notifyAll()是三个定义在Object类里的方法,能够用来控制线程的状态。
        这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不一样可能有些许差别。
         若是对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,而后处于等待状态。
        若是对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程能够继续运行。
        若是对象调用了notifyAll方法就会通知全部等待这个对象控制权的线程继续运行。

十一、线程怎样返回结果?如何获取?

十二、说说violatile关键字有什么用,和Synchronized有什么区别?
刷新内存,不读取缓存.每次变量更新都取最新的

1三、假如新建T一、T二、T3三个线程,如何保证它们按顺序执行?

    T1.start();
    T1.join();
    T2.start();
    T2.join();
    T3.start();
    
1四、怎么控制同一时间只有3个线程运行?
    使用只有三个线程的线程池

1五、为何要使用线程池?
    节约频繁建立线程和释放资源的开支

1六、说一说经常使用的几种线程池并讲讲其中的工做原理。

1七、线程池启动线程submit()和execute()有什么不一样?
    JDK5日后,任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。二者均可以被ExecutorService执行,它们的区别是:
    execute(Runnable x) 没有返回值。能够执行任务,但没法判断任务是否成功完成。——实现Runnable接口
    submit(Runnable x) 返回一个future。能够用这个future来判断任务是否成功完成。——实现Callable接口

1八、说说多线程并发控制中的倒计时器、循环栅栏是什么,有什么应用场景?

1九、什么是活锁、饥饿、无锁、死锁?
        活锁这个概念你们应该不多有人据说或理解它的概念,而在多线程中这确实存在。活锁偏偏与死锁相反,死锁是你们都拿不到资源都占用着对方的资源,
    而活锁是拿到资源却又相互释放不执行。当多线程中出现了相互谦让,都主动将资源释放给别的线程使用,这样这个资源在多个线程之间跳动而又得不到执行,这就是活锁。
        咱们知道多线程执行中有线程优先级这个东西,优先级高的线程可以插队并优先执行,这样若是优先级高的线程一直抢占优先级低线程的资源,
    致使低优先级线程没法获得执行,这就是饥饿。固然还有一种饥饿的状况,一个线程一直占着一个资源不放而致使其余线程得不到执行,
    与死锁不一样的是饥饿在之后一段时间内仍是可以获得执行的,如那个占用资源的线程结束了并释放了资源。
        无锁,即没有对资源进行锁定,即全部的线程都能访问并修改同一个资源,但同时只有一个线程能修改为功。无锁典型的特色就是一个修改操做在一个循环内进行,
    线程会不断的尝试修改共享资源,若是没有冲突就修改为功并退出不然就会继续下一次循环尝试。因此,若是有多个线程修改同一个值一定会有一个线程能修改为功,
    而其余修改失败的线程会不断重试直到修改为功。
        死锁是多线程中最差的一种状况,多个线程相互占用对方的资源的锁,而又相互等对方释放锁,此时若无外力干预,这些线程则一直处理阻塞的假死状态,造成死锁。
20、什么是原子性、可见性、有序性?
    即一个操做或者多个操做,要么所有执行而且执行的过程不会被任何因素打断,要么就都不执行。原子性就像数据库里面的事务同样,他们是一个团队,同生共死。
    可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其余线程可以当即看获得修改的值。
    即程序执行的顺序按照代码的前后顺序执行

2一、什么是守护线程?有什么用?
    守护线程
    守护线程一般执行一些任务,当全部非守护线程终止的时候,JVM简单的丢弃掉全部现存的守护线程.一旦其它非守护线程执行完,不必定全部的守护线程都会执行完才退出,它们可能在非守护线程执行完后的某个时刻退出.
    使用场景
    来为其它线程提供服务支持.
    守护线程的建立
    为了建立一个守护线程,须要在调用thread.start()方法以前调用thread.setDeamon()方法.

2二、怎么中断一个线程?如何保证中断业务不影响?

2三、yield()方法有什么用?
    理论上,yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其余线程占用本身的位置。这代表该线程没有在作一些紧急的事情。
    注意,这仅是一个暗示,并不能保证不会产生任何影响。
    让咱们列举一下关于以上定义重要的几点:
        Yield是一个静态的原生(native)方法
        Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。
        Yield不能保证使得当前正在运行的线程迅速转换到可运行的状态
        它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态

2四、什么是重入锁,和Synchronized锁有什么区别?
    https://www.cnblogs.com/baizhanshi/p/7211802.html

2五、Synchronized有哪几种用法?
    同步方法
    同步代码块

2六、Fork/Join框架是干什么的?
    Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每一个小任务结果后获得大任务结果的框架
    https://www.cnblogs.com/senlinyang/p/7885964.html
    
2七、如何给线程传递参数?
    1、经过构造函数传递参数
    2、经过变量和方法传递数据
    3、经过回调函数传递数据
    https://www.cnblogs.com/xql4j/articles/3242118.html

2八、说说线程安全的和不安全的集合。
    其中Vector、HashTable、Properties是线程安全的。其中ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是线程不安全的。
    (线程不安全是指:当多个线程访问同一个集合或Map时,若是有超过一个线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。)
    https://blog.csdn.net/weixin_40773253/article/details/78527660

2九、什么是CAS算法?在多线程中有哪些应用。

    https://blog.csdn.net/Jbinbin/article/details/86212688

30、你遇到过哪些多线程的问题?都是如何解决的?