6.JAVA基础面试题:线程

六.JAVA基础面试题:线程


1.什么是线程?什么是进程?进程和线程之间的关系?

2.并行和并发的区别

3.同步和异步的区别

4.为什么要有多线程?多线程产生的问题?

5.线程的生命周期和状态

6.什么是上下文的切换?上下文切换的时机

7.sleep和wait的区别

8.什么是死锁?如何预防死锁

9.Thread类的run方法可以直接使用


1.什么是指令重排序

2.JMM是什么

3.JAVA内存结构和JMM的区别

4.并发编程的三个特性


1.如何禁止指令重排序和保证可见性

2.乐观锁和悲观锁是什么?

3.synchronized是什么?有什么用处?

4.synchronized和volatile的区别

5.ReentrantLock是什么

6.ReentrantLock和sychronized的区别


1.ThreadLoacl有什么用?原理是什么?如何造成内存泄漏的

2.什么是线程池?线程池的好处

3.如何创建线程池

4.Future类的优点

5.FutureTask和Callable的关系

6.AQS的理解


六.JAVA基础面试题:线程


1.什么是线程?什么是进程?进程和线程之间的关系?

  • 启动程序后,JVM启动了一个进程,而main函数则启动了一个线程。
  • 各个进程相互独立,一个进程可以有多个线程。
  • 多个线程之间共享方法区和堆
  • 每个线程都有自己的程序计数器,本地方法栈和虚拟机栈(保证程序切换后仍能正确执行,保证线程内容不会被其他线程所破坏)

2.并行和并发的区别

  • 并行:两个作业在同一时间段执行
  • 并发:两个作业在同一时刻执行

3.同步和异步的区别

  • 同步:发出调用后未返回结果则一直等待
  • 异步:发出调用后不用等待结果则直接返回

4.为什么要有多线程?多线程产生的问题?

  • 互联网的趋势:并发量很大,需要多线程来提高并发能力
  • 计算机的发展:多核cpu,一个线程可以用一个cpu
  • 多线程带来的问题
    内存泄漏
    死锁
    线程不安全

5.线程的生命周期和状态

  • 新建-就绪-运行-死亡
  • 运行-阻塞-就绪

6.什么是上下文的切换?上下文切换的时机

  • 即JVM保存当前线程的上下文,加载下一个占用cpu的线程上下文
  • 上下文切换的时机
    主动让出cpu(sleep,wait)
    时间片用完
    线程被阻塞(io)
    线程执行结束

7.sleep和wait的区别

  • sleep用在暂停线程,过了时间即可继续。不会释放锁。用于线程内。Thread类的静态方法。

  • wait用在线程通信,其他线程notify才可继续。会释放锁。用在同步代码块内。Object类的方法。

8.什么是死锁?如何预防死锁

  • 多个线程同时被阻塞,且都等待资源的释放,无限阻塞。
  • 预防死锁
    一次性申请所有资源。
    申请不到资源则释放已占有资源。
    按顺序获取资源。

9.Thread类的run方法可以直接使用

  • Thread类的run方法可以调用但只是普通方法,不会开启线程
  • 需要用start来开启线程

1.什么是指令重排序

  • 指令重排序
    系统执行代码不一定要按照编写代码的顺序执行代码
  • 重排序
    编译器优化重排(不改变线程的语义)
    指令并行重排(流水线并行技术)
    内存系统重排
  • 产生问题
    保证单线程语义一致,但是无法保证多线程语义一致。

2.JMM是什么

  • JMM是java内存模型
    主要是为了规范并发
  • JMM两大结构
    主内存:全部线程创建的实例对象都放入主内存中
    本地内存:每个线程都有本地内存来存储共享变量的副本,通过主内存和本地内存交互来更新,每个线程只能访问自己的本地内存

3.JAVA内存结构和JMM的区别

  • JAVA内存结构是JVM运行时的内存区域
  • JMM是规范线程并发的内存关系

4.并发编程的三个特性

  • 原子性:要么执行要么都不执行
  • 可见性:其他线程要能够立刻看到修改后的变量
  • 有序性:指令执行有序

1.如何禁止指令重排序和保证可见性

  • 使用volatile关键字(无法保证原子性)
  • 使用共享变量时直接导主内存中获取
  • 特定的内存屏障禁止指令重排序

2.乐观锁和悲观锁是什么?

  • 乐观锁
    每次访问不出现问题,只需要提交验证即可。
    CAS自旋锁。
    可能出现ABA问题,适用于少量读。
  • 悲观锁
    每次访问都有可能出现问题。
    synchronized和ReentrantLock。
    一次只能一个线程访问,适用于大量读。

3.synchronized是什么?有什么用处?

  • 被它修饰的代码块同一时刻只能有一个线程执行
  • 修饰
    实例方法(当前对象为锁)
    静态方法(当前类的锁)
    代码块(指定的锁)
  • 注意:构造方法不需要使用synchronized修饰,因为构造方法本身就是线程安全的。

4.synchronized和volatile的区别

  • volatie,变量,可见性,性能较好
  • synchronized,方法和代码块,可见性+原子性

5.ReentrantLock是什么

  • 是一个可重入独占式的锁
    可重入:线程内部调用线程的锁可以继续获得锁
    独占式:其他线程不可读不可写(排他锁)

6.ReentrantLock和sychronized的区别

  • 都是可重入的锁
  • sychronized 非公平锁(先看是否能获得锁再进入排队队列),自动加锁释放,JVM(操作系统级别)依赖于对象监视器Monitor
  • ReentrantLock 公平或非公平锁,手动加锁释放,API级别

1.ThreadLoacl有什么用?原理是什么?如何造成内存泄漏的

  • threadlocal可以让每个线程绑定自己的值,即访问变量的每个线程都有自己的本地副本
  • 原理
    每个线程都有一个ThreadLocalMap,存储以Threadloc为键,以Object为值
  • 内存泄漏
    垃圾回收机制只清理key而不清理value。
    但是ThreadLocalMap的机制有在调用方法时,自动清理所有key为null的记录。

2.什么是线程池?线程池的好处

  • 线程池是管理一系列线程的资源地
  • 线程池的好处
    提高线程的可管理性
    降低资源消耗

3.如何创建线程池

  • 利用ThreadPoolExecutor为构造函数
  • Executor工具类的Executors来创建

4.Future类的优点

  • Future是异步思想的运用

5.FutureTask和Callable的关系

  • FutureTask 是任务+结果(可以异步获取执行结果)
  • FutureTask仅执行一次
  • FutureTask本身不能创建线程,需要Thread
  • 并且实现了Callable接口的类可以当做参数传入FutureTask开启线程(可以获得结果)

6.AQS的理解

  • AQS是抽象队列同步器,是ReentrantLock的核心组件。
  • AQS如何实现的
    有一个state变量(当被加锁时,则将state从0改成1)
    有一个保存线程的变量(当被加锁时,将该变量从null变为加锁的线程)
    有一个线程等待队列(如果state值不是0,那么线程进入等待队列)
  • 实战时
    可重入锁:如果判断加锁的是自己,那么可以继续将state从1变到2…3,如果判断加锁的不是自己且state不是0,那么进入等待队列。

你可能感兴趣的:(面试题,java,jvm,面试)