zoukankan      html  css  js  c++  java
  • 40道经典java多线程面试题

    40道经典java多线程面试题

    题目来源

    看完了java并发编程的艺术,自认为多线程“大成”,然后找了一些面试题,也发现了一些不足。

    一下问题来源于网上的博客,答案均为本人个人见解,若有疑问或错误欢迎讨论。QQ:1807812486

    1.什么是线程

    线程是操作系统能够进行运算调度的最小单位,它被包含在进程当中,是进程的实际运作单位。
    

    2.线程和进程的区别

    一个进程是一个独立的运行环境,它可以被看做是一个程序或应用。线程是进程中执行的一个任务。线程是进程的子集,一个进程可以有多个线程。进程独占一片内存,进程共享内存。
    

    3.CyclicBarrier和CountDownLatch有什么不同

    CountDownLatch和CyclicBarrier都用于让线程等待,达到一定条件时再运行。CountDownlatch更加灵活可以在一个线程中多次使用,但是不能重置计数器。CyclicBarrier更加强大,可以重置计数器reset(),可以检查被阻塞的数目,可以检查被阻塞的线程是否被中断。
    

    4.java内存模型是什么(JMM java Memory Model)

    java内存模型规定和指引java程序在不同的内存架构,CPU,操作系统中有确定性的行为。JMM定义了线程与主存之间的关系,JMM控制一个线程的共享变量的写入何时对另一个线程可见。
    

    5.happens-before原则

    • 程序顺序规则:一个线程中的任意操作happens-before该线程中的任意后续操作
    • 监视器锁原则:对于一个锁的解锁happens-before该锁的加锁。
    • volatile变量原则:volatile写happens-before volatile读
    • 传递性原则:A happens-before B B happens-before C A happens-before C.

    A happens-before B 并不是 A比B先执行,而是A的执行结果对B可见。且 A按顺序排在B之前

    6.Java中的volatile变量是什么

    Volatile是成员变量的修饰符,能够保证该变量在多线程中的可见性。实现原理是将写缓存刷新到主存中,然后根据缓存一致性原则保证可见性。
    

    7.什么是线程安全?Vector是一个安全类吗

    在多线程中每一次读的数据和预期数据一样就是线程安全(此描述不够准确)
    

    8.如何实现两个线程间共享数据

    1.通过类变量直接将数据放到主存中
    2.通过并发的数据结构来存储数据
    3.使用volatile变量或者锁
    4.调用atomic类
    

    9.为什么wait(),notify(),notifyAll()在对象中,而不在Thread类中

    java中锁的级别是对象级而不是线程级,每个对象都有锁,通过线程获得。如果wait()方法在线程中,线程正在等待的是哪个锁就不明显了。
    

    10.什么是ThreadLocal变量

    ThreadLocal变量是一种特殊的变量,它可以将变量保存副本ThreadLocalMap中供每个线程单独使用。
    ThreadLocal 详细解析
    1.ThreadLocal的结构
      成员变量: threadLocalHashCode   用来区分不同的ThreadLocal
      静态内部类:ThreadLocalMap       用来存储ThreadLocal
      方法set(): 通过获取当前线程t,然后获得一个threadlocalmap。第一次使用ThreadLocal时会初始化一个ThreadLocalMap,然后复制给当前线程。
    

    11.什么是futureTask

    RunnableFuture继承了Runnable接口和Future接口。它可以取消和启动一个线程的运行,当调用该类的线程未完成时调用get()会阻塞调用线程,当线程已经完成时会返回结果。futureTask的底层实现原理是AQS 
    

    12.java中interrupt(),interrupted()和isInterrupted()的区别

    interrupt()是一个成员方法,调用时会改变中断状态,但是不会中断线程,只有catch后会中断线程。
    interrupted()是一个静态方法,会中断线程,中断状态为true。
    isInterrupted()是一个成员方法,会中断线程,中断状态为false。
    
    	public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }
    
        public boolean isInterrupted() {
            return this.isInterrupted(false);
        }
    
        private native boolean isInterrupted(boolean var1);
        上面是源码,也就是说都调用的是本地方法,只是传入的参数不一样而已。
    

    13.为什么wait和notify方法要在同步块中调用?

    wait和notify都需要获得对象锁
    

    14.为什么你应该在循环中检查等待条件?

    代码

    因为处于等待的线程可能会被假唤醒和错误警报,如果不在循环中等待可能会因为没有满足条件就退出等待。比如说,退出等待的条件是list()不为空,有7个线程在等待。当list为空时7个都将被唤醒,删除元素会报错。
    

    15.同步集合和并发集合有什么不一样

    同步集合的锁用的是sychronized,比较武断。并发集合的锁用的是AQS,灵活性更高,扩展性更强。
    

    16. 有三个线程T1,T2,T3,怎么确保它们按顺序执行(确保main()方法所在的线程是Java程序最后结束的线程)?

    使用CountDownLatch()和ClclicBarrier方法都可以实现main()方法最后执行。在前一个线程调用后一个线程的join()方法可以按顺序执行。
    

    17.如果你提交任务时,线程池队列已满。会时发会生什么?

    如果coreSize<maxSize 则会创建新的线程来执行任务。如果coreSize=MaxSize 会抛出一个RejectExecutionException.
    

    18.你对线程优先级的理解是什么?

    多线程其实是对CPU的轮询执行,只是CPU处理的速度太快了感觉不到上下文的切换。优先级就是CPU轮询线程的概率,优先级越高概率越高,优先级越低概率越低。
    

    19.什么是线程池

    线程池是管理多线程的一种工具,一个进程可以创建的线程数量是有限的,通过线程池创建的线程执行完成一个任务后不会立即关闭,而是继续执行阻塞队列中的线程直到阻塞线程为空。
    

    20.有那些阻塞队列

    ArrayBlockingQueue       一个由数组构成的有界阻塞队列
    LinkedBlockingQueue      一个由链表构成的有界阻塞队列
    PriorityBlockingQueue    一个支持优先级排序的无界阻塞队列
    DelayQueue               一个使用优先队列实现的无界阻塞队列。
    SynchroniouQueue         一个不储存元素的阻塞队列
    LinkedTransferQueue      一个由链表结构组成的无界阻塞队列
    LinkedBlockingDeque      一个由链表结构组成的双向阻塞队列
    

    21.Java中synchronized 和 ReentrantLock 有什么不同?

    synchronized是一个隐式的重入锁,比较笨重,实现方式是锁主存和缓存一致性。
    reentrantLock是一个显示的重入锁,比较灵活,可以扩展为分段锁,实现方式是AQS.
    

    22.如何避免死锁?

    死锁发生的条件是
    1.存在循环等待
    2.存在资源竞争
    3.不剥夺条件,已经获得的资源不会被剥夺
    4.请求与保持,一个线程因请求资源被阻塞时,拥有资源的线程的状态不会改变。
    避免死锁只需要破环其中的一个条件就可以了。
    

    23. 怎么检测一个线程是否拥有锁?

    Thread中有一个holdLock()方法,当且仅当当前线程拥有某个具体的对象锁时返回true
    

    24.JVM中哪个参数是用来控制线程的栈堆栈小的

    -Xss    
    

    25. Thread类中的yield方法有什么作用?

    它会会通知cpu在此处可以更换切片,更不更换由cpu自己决定。(yield可以暂停当前正在执行的线程对象,让其他有线程执行)
    

    26.Java中ConcurrentHashMap的并发度是什么?

    并发度就是segment的个数,通常是2的N次方。默认是16
    

    27.java中的Semaphore是什么

    它是一个新的同步类,是一个计数信号。比如在数据库连接池中,假设我们只能获得10个数据库连接,20大小的线程池。此时我们就可以用一个Semaphore来表示数据库连接池的数目,当需要使用时就accquire()取得许可,使用完毕就release()添加一个许可。
    

    28. 什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?

    线程调度器是一种操作系统服务,它负责给线程任务分配CPU处理的时间。时间分片指的是CPU一次性处理的一个任务的片段,分配CPU时间可以基于线程优先级或者线程等待时间,但是线程调度并不收到JVM的控制。
    

    29.在多线程中,什么是上下文切换(context-switching)?

    上线文切换是指CPU存储和恢复状态的过程,它使得线程能够从中断状态恢复继续运行。
    

    30.如何在Java中创建Immutable对象?

    将类和成员变量都设置为final,且成员为私有,成员的初始化通过构造参数初始化。不提供setter()方法。immutable的好处是在没有同步的情况下是线程安全的。
    

    31. Java中的ReadWriteLock是什么?

    它的名称是读写锁,实现原理是AQS.它将32位的 state状态变量分为前16位和后16位,前16位状态表示为读的状态,后16位状态表示为写的状态。也就是说读写锁有两把锁,一把控制读,一把控制写。写锁和写锁互斥,写锁和读锁互斥,读锁和互锁相容,写锁可以降级为读锁。
    

    32.多线程中的忙循环是什么?

    忙循环是指程序员用循环来代替wait()方法让线程进入等待,它的好处是可以占用CPU,不放弃缓存可以减少将数据读入缓存的时间。
    

    33.volatile 变量和 atomic 变量有什么不同?

    volatile的实现方式是将缓存中的值刷新到主存中,本生具有可见性和原子性但是volatile++不具有原子性。
    atomic的实现方式是CAS.本质有点类似,也是缓存一致性原则。
    

    34.单例模式的双检锁是什么?

    当实例为空时,加锁再判断是否为空。如果为空则创建一个新的实例。
    安全吗?不安全
    原因:在创建一个对象的时候会分为三个步骤   1.为对象分配内存    2.在内存中初始化一个对象  3.将对象指配给使用者。步骤2依赖于1,所以不会被重排序。步骤3和步骤2没有依赖可能会被重排序。所以当另外一个线程在此时调用单例可能会获得一个空的实例。
    

    35.如何在java中创建线程安全的Singleton

    1.先加锁,再判断。
    2.用一个volatile变量进行标识。
    3.反射
    

    36. 写出3条你遵循的多线程最佳实践

    • 多用同步类,少用wait,notify
    • 少用锁,应当缩小同步范围
    • 给线程一个自己的名字
    • 多用并发集合少用同步集合

    37.如何强制启动一个线程?

    我觉得没有方法强制启动,就像垃圾回收一样,即使调用了System.gc也不会马上就gc。因为java中的一个线程和操作系统中的一个线程是一一对应的。操作系统的线程什么时候在cpu上轮询由操作系统决定,jvm没有权限就像优先级一样。
    

    38.java中的fork/join框架是什么

    它是jdk7中的一款高效并发编程工具,它利用工作窃取算法将一个大任务划分为若干个子任务,然后将子任务结果合并起来,从而提高了并发编程的效率。
    

    39.线程调度策略?

    1.抢占式调度策略
      处于就绪态的线程,根据优先级抢占进入运行态。
    2.时间片轮转调度策略
      所有处于就绪状态的线程中选择优先级最高的线程分配一定的CPU时间运行,该时间过后再选择其他线程运行。
    

    40.在线程中你怎么处理不可捕捉异常?

    hread.UncaughtExceptionHandler是java SE5中的新接口,它允许我们在每一个Thread对象上添加一个异常处理器。
  • 相关阅读:
    activeMQ
    读写xml
    PLSQL
    oracle语法
    cxf远程调用服务
    FastDFS在linux下的安装和整合nginx实现上传图片和url访问
    dubbo和zookeeper的应用
    solr和Lucene的配置方式和应用
    win10 下安装 MongoDB 数据库支持模块(python)
    nodeJs 对 Mysql 数据库的 curd
  • 原文地址:https://www.cnblogs.com/c-lover/p/10741005.html
Copyright © 2011-2022 走看看