美文网首页面试相关面试
面试相关之 Java 并发

面试相关之 Java 并发

作者: Kevin_小飞象 | 来源:发表于2019-02-13 17:11 被阅读0次

    1. sleep()和wait()的区别?
    参考回答:
    sleep()来自Thread类;wait()来自Object类
    sleep()用于线程控制自身流程;而wait()用于线程间通信,配合notify()/notifyAll()在同步代码块或同步方法里使用
    sleep()的线程不会释放对象锁;wait()会释放对象锁进入等待状态,使得其他线程能使用同步代码块或同步方法

    2. synchronized同步代码块还有同步方法本质上锁住的是谁?为什么?
    参考回答:
    本质上锁住的是对象。在java虚拟机中,每个对象和类在逻辑上都和一个监视器相关联,synchronized本质上是对一个对象监视器的获取。当执行同步代码块或同步方法时,执行方法的线程必须先获得该对象的监视器,才能进入同步代码块或同步方法;而没有获取到的线程将会进入阻塞队列,直到成功获取对象监视器的线程执行结束并释放锁后,才会唤醒阻塞队列的线程,使其重新尝试对对象监视器的获取。

    3. synchronized和volatile的区别?
    参考回答:
    synchronized能保证操作的原子性,而volatile不可以,假设线程A和线程B同时读取到变量a值,A修改a后将值更新到主内存,同时B也修改a值会覆盖A的修改操作
    synchronized可修饰变量、方法和类,而volatile只能修饰变量
    synchronized可能会造成线程阻塞,而volatile不会造成线程的阻塞

    4. ReentrantLock和synchronized的区别?
    参考回答:
    ReentrantLock与synchronized的不同在于ReentrantLock:
    等待可中断:当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。
    公平锁:多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。而synchronized是非公平的,即在锁被释放时,任何一个等待锁的线程都有机会获得锁。ReentrantLock默认情况下也是非公平的,但可以通过带布尔值的构造函数改用公平锁。
    锁绑定多个条件:一个ReentrantLock对象可以通过多次调用newCondition()同时绑定多个Condition对象。而在synchronized中,锁对象wait()和notify()或notifyAl()只能实现一个隐含的条件,若要和多于一个的条件关联不得不额外地添加一个锁。

    5. 什么是线程安全?保障线程安全有哪些手段?
    参考回答:
    线程安全就是当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。保证线程安全可从多线程三特性出发:
    原子性(Atomicity):单个或多个操作是要么全部执行,要么都不执行
    Lock:保证同时只有一个线程能拿到锁,并执行申请锁和释放锁的代码
    synchronized:对线程加独占锁,被它修饰的类/方法/变量只允许一个线程访问
    可见性(Visibility):当一个线程修改了共享变量的值,其他线程能够立即得知这个修改
    volatile:保证新值能立即同步到主内存,且每次使用前立即从主内存刷新;
    synchronized:在释放锁之前会将工作内存新值更新到主存中
    有序性(Ordering):程序代码按照指令顺序执行
    volatile: 本身就包含了禁止指令重排序的语义
    synchronized:保证一个变量在同一个时刻只允许一条线程对其进行lock操作,使得持有同一个锁的两个同步块只能串行地进入

    6. 线程的有哪些状态?
    参考回答:
    在任意一个时间点,一个线程只能有且只有其中的一种状态:

    • 新建(New):线程创建后尚未启动
    • 运行(Runable):包括正在执行(Running)和等待着CPU为它分配执行时间(Ready)两种
      无限期等待(Waiting):该线程不会被分配CPU执行时间,要等待被其他线程显式地唤醒。以下方法会让线程陷入无限期等待状态:
      没有设置Timeout参数的Object.wait()
      没有设置Timeout参数的Thread.join()
      LockSupport.park()
      限期等待(Timed Waiting):该线程不会被分配CPU执行时间,但在一定时间后会被系统自动唤醒。以下方法会让线程进入限期等待状态:
      Thread.sleep()
      设置了Timeout参数的Object.wai()
      设置了Timeout参数的Thread.join()
      LockSupport.parkNanos()
      LockSupport.parkUntil()
    • 阻塞(Blocked):线程被阻塞。和等待状态不同的是,阻塞状态表示在等待获取到一个排他锁,在另外一个线程放弃这个锁的时候发生;而等待状态表示在等待一段时间或者唤醒动作的发生,在程序等待进入同步区域的时候发生。
    • 结束(Terminated):线程已经结束执行

    7. Thread的join()有什么作用?
    参考回答:
    Thread 的 join() 的含义是等待该线程终止,即将挂起调用线程的执行,直到被调用的对象完成它的执行。比如存在两个线程 t1 和 t2,下述代码表示先启动 t1,直到 t1 的任务结束,才轮到 t2启动。

    t1.start();
    t1.join(); 
    t2.start();
    

    8. 同步和非同步、阻塞和非阻塞的概念
    参考回答:
    同步和异步体现的是消息的通知机制:所谓同步,方法A调用方法B后必须等到方法B返回结果才能继续后面的操作;所谓异步,方法A调用方法B后可让方法B在调用结束后通过回调等方式通知方法A
    阻塞和非阻塞侧重于等待消息时的状态:所谓阻塞,就是在结果返回之前让当前线程挂起;所谓非阻塞,就是在等待时可做其他事情,通过轮询去询问是否已返回结果

    9. 销毁一个线程的方法有哪些?
    参考回答
    (1)设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止
    (2)使用interrupt()方法中断线程
    (3)使用stop方法强行终止线程(不推荐)

    10. 什么是线程池,如何使用?
    参考回答:
    什么是线程池: java.util.concurrent.Executors提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。

    常见线程池
    ①newSingleThreadExecutor单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务
    ②newFixedThreadExecutor(n)固定数量的线程池,没提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行
    ③newCacheThreadExecutor(推荐使用)可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。
    ④newScheduleThreadExecutor大小无限制的线程池,支持定时和周期性的执行线程

    11. 多线程断点续传的实现原理?

    12. 了解Java新特性
    面向 Java 开发人员的 Oracle 技术网
    开源中国

    相关文章

      网友评论

        本文标题:面试相关之 Java 并发

        本文链接:https://www.haomeiwen.com/subject/yuvdeqtx.html