并发编程面试八股文背诵版

文章目录:

  • 什么是进程?是什么线程? * * *

  • 进程和线程的关系?(区别) * * *

  • 并行和并发的区别? *

  • 多线程的优缺点(为什么使用多线程、多线程会引发什么问题) * *

  • 线程的上下文切换 *

  • Java中守护线程和用户线程的区别? *

  • 线程死锁是如何产生的,如何避免 * * *

  • 用Java实现死锁,并给出避免死锁的解决方案        *     *

  • Java中的死锁、活锁、饥饿有什么区别? *

  • 线程的生命周期和状态 * * *

  • 创建线程一共有哪几种方法? * * *

  • runnable 和 callable 有什么区别? * * *

  • 线程的run()和start()有什么区别?  *    *     *

  • 为什么调用start()方法时会执行run()方法,而不直接执行run()方法?   *     *      *

  • 线程同步和线程调度相关的方法问题

    • 线程同步以及线程调度相关的方法有哪些? * * *

    • 线程的sleep()方法和yield()方法有什么不同?   *     *      *

    • sleep()方法和wait()方法的区别?      *     *    *

    • wait()方法一般在循环块中使用还是if块中使用?    *     *     *

    • 线程通信的方法有哪些? * * *

    • 为什么wait()、notify()、notifyAll()被定义在Object类中而不是在Thread类中?    *     *

    • 为什么wait(),notify()和notifyAll()必须在同步方法或者同步块中被调用?    *     *

    • 为什么Thread类的sleep()和yield()方法是静态的? *

    • 如何停止一个正在运行的线程? * *

    • 如何唤醒一个阻塞的线程?    *      *

    • Java如何实现两个线程之间的通信和协作?    *      *

    • 同步方法和同步方法块哪个效果更好?    *     *

    • 什么是线程同步?什么是线程互斥?他们是如何实现的? * * *

    • 在Java程序中如何保证线程的运行安全?    *     *      *

    • 线程类的构造方法、静态块是被哪个线程调用的?    *

    • 一个线程运行时异常会发生什么?      *

    • 线程数量过多会造成什么异常? *

  • 三个线程T1、T2、T3,如何让他们按顺序执行? * * *

  • synchronized关键字 * * *

    • 什么是synchronized关键字?

    • Java内存的可见性问题

    • synchronized关键字三大特性是什么?

    • synchronized关键字可以实现什么类型的锁?

    • synchronized关键字的使用方式

    • synchronized关键字的底层原理

    • Jdk1.6为什么要对synchronized进行优化?

    • jDK1.6对synchronized做了哪些优化?

  • volatile关键字 * * *

    • volatile的作用是什么?

    • volatile的特性有哪些?

    • Java内存的可见性问题

    • 为什么代码会重排序?

    • 重排序会引发什么问题?

    • as-if-serial规则和happens-before规则的区别?

    • voliatile的实现原理?

    • volatile实现内存可见性原理

    • volatile实现有序性原理

    • 编译器对内存屏障插入策略的优化

    • volatile能使一个非原子操作变成一个原子操作吗?

    • volatile、synchronized的区别?

  • ConcurrentHashMap * * *

    • 什么是ConcurrentHashMap?相比于HashMap和HashTable有什么优势?

    • java中ConcurrentHashMap是如何实现的?

    • ConcurrentHashMap结构中变量使用volatile和final修饰有什么作用?

    • ConcurrentHashMap有什么缺点?

    • ConcurrentHashMap默认初始容量是多少?每次扩容为原来的几倍?

    • ConCurrentHashMap 的key,value是否可以为null?为什么?HashMap中的key、value是否可以为null?

    • ConCurrentHashmap在JDK1.8中,什么情况下链表会转化为红黑树?

    • ConcurrentHashMap在JDK1.7和JDK1.8版本中的区别?

    • ConcurrentHashMap迭代器是强一致性还是弱一致性?

  • ThreadLocal * * *

    • 什么是ThreadLocal?有哪些应用场景?

    • ThreadLocal原理和内存泄露?

  • 线程池 * * *

    • 什么是线程池?为什么使用线程池

    • 创建线程池的几种方法

    • ThreadPoolExecutor构造函数的重要参数分析

    • ThreadPoolExecutor的饱和策略(拒绝策略)

    • 线程池的执行流程

    • execute()方法和submit()方法的区别

  • CAS * * *

    • 什么是CAS?

    • CAS存在的问题

    • CAS的优点

  • Atomic 原子类 * *

  • AQS * *

    • 什么是AQS?

    • AQS的原理

    • AQS的资源共享方式有哪些?

    • 如何使用AQS自定义同步器?

什么是进程?是什么线程? * * *

线程是处理器任务调度和执行的基本单位,进程是操作系统资源分配的基本单位。

进程是程序的一次执行过程,是系统运行的基本单位。线程是一个比进程更小的执行单位,一个进程可以包含多个线程。

进程和线程的关系?(区别) * * *

定义:线程是处理器任务调度和执行的基本单位;进程是操作系统资源分配的基本单位。

包含关系:一个进程可以包含多个线程。

从Java虚拟机的角度来理解:Java虚拟机的运行时数据区包含堆、方法区、虚拟机栈、本地方法栈、程序计数器。各个进程之间是相互独立的,每个进程会包含多个线程,每个进程所包含的多个线程并不是相互独立的,这个线程会共享进程的堆和方法区,但这些线程不会共享虚拟机栈、本地方法栈、程序计数器。即每个进程所包含的多个线程共享进程的堆和方法区,并且具备私有的虚拟机栈、本地方法栈、程序计数器,如图所示,假设某个进程包含三个线程。

由上面可知以下进程和线程在以下几个方面的区别:

内存分配:进程之间的地址空间和资源是相互独立的,同一个进程之间的线程会共享线程的地址空间和资源(堆和方法区)。

资源开销:每个进程具备各自的数据空间,进程之间的切换会有较大的开销。属于同一进程的线程会共享堆和方法区,同时具备私有的虚拟机栈、本地方法栈、程序计数器,线程之间的切换资源开销较小。

并行和并发的区别? *

并行:单位时间多个处理器同时处理多个任务。

并发:一个处理器处理多个任务,按时间片轮流处理多个任务。

多线程的优缺点(为什么使用多线程、多线程会引发什么问题) * *

优点:当一个线程进入等待状态或者阻塞时,CPU可以先去执行其他线程,提高CPU的利用率。

缺点:

  • 上下文切换:频繁的上下文切换会影响多线程的执行速度。

  • 死锁

  • 资源限制:在进行并发编程时,程序的执行速度受限于计算机的硬件或软件资源。在并发编程中,程序执行变快的原因是将程序中串行执行的部分变成并发执行,如果因为资源限制,并发执行的部分仍在串行执行,程序执行将会变得更慢,因为程序并发需要上下文切换和资源调度。

线程的上下文切换 *

即便是单核的处理器也会支持多线程,处理器会给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给每个线程的执行时间,一般来说时间片非常的短,所以处理器会不停地切换线程。

CPU会通过时间片分配算法来循环执行任务,当前任务执行完一个时间片后会切换到下一个任务,但切换前会保存上一个任务的状态,因为下次切换回这个任务时还要加载这个任务的状态继续执行,从任务保存到在加载的过程就是一次上下文切换。

Java中守护线程和用户线程的区别? *

任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on) 设置,true则是将该线程设置为守护线程,false则是将该线程设置为用户线程。同时,Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。

用户线程:平时使用到的线程均为用户线程。

守护线程:用来服务用户线程的线程,例如垃圾回收线程。

守护线程和用户线程的区别主要在于Java虚拟机是后存活。

用户线程:当任何一个用户线程未结束,Java虚拟机是不会结束的。

守护线程:如何只剩守护线程未结束,Java虚拟机结束。

线程死锁是如何产生的,如何避免 * * *

这块内容很重要,面试时也可能让手写死锁的代码示例。

死锁:由于两个或两个以上的线程相互竞争对方的资源,而同时不释放自己的资源,导致所有线程同时被阻塞。

死锁产生的条件:

  • 互斥条件:一个资源在同一时刻只由一个线程占用。

  • 请求与保持条件:一个线程在请求被占资源时发生阻塞,并对已获得的资源保持不放。

  • 循环等待条件:发生死锁时,所有的线程会形成一个死循环,一直阻塞。

  • 不剥夺条件:线程已获得的资源在未使用完不能被其他线程剥夺,只能由自己使用完释放资源。

避免死锁的方法主要是破坏死锁产生的条件。

  • 破坏互斥条件:这个条件无法进行破坏,锁的作用就是使他们互斥。

  • 破坏请求与保持条件:一次性申请所有的资源。

  • 破坏循环等待条件:按顺序来申请资源。

  • 破坏不剥夺条件:线程在申请不到所需资源时,主动放弃所持有的资源。

用Java实现死锁,并给出避免死锁的解决方案        *     *

class DeadLockDemo {
    private static Object resource1 = new Object();
    private static Object resource2 = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resource1) {
                System.out.println(Thread.currentThread() + "get resource1");
                try {
                    Thread.sleep(1000);   //线程休眠,保证线程2先获得资源2
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值