Java面试题冲刺第二十五天--并发编程3

目录
  • 面试题1:你了解线程池么?简单介绍一下。
    • 追问1:连接池 和 线程池是一个意思么?有什么区别?
      • 不同点
  • 面试题2:线程池中核心线程数量大小你是怎么设置的?
    • 追问1:核心线程数量过大或过小会造成什么后果?
  • 面试题3:线程池都有哪些状态呀?
    • 追问1:什么条件下会进入TERMINATED状态
  • 总结

面试题1:你了解线程池么?简单介绍一下。

java提供的一个java.util.concurrent.Executor接口的实现用于创建线程池。

线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理。如果每个请求都创建一个线程去处理,那么服务器的资源很快就会被耗尽,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

假设一个服务器完成一项任务,创建线程时间T1 ,在线程中执行任务的时间T2,销毁线程时间为T3。如果:T1 + T3 远大于 T2,则可以采用线程池,大大缩短T1、T3时间,以提高服务器性能。

一个线程池包括以下四个基本组成部分:

1.线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;

2.工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;

3.任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;

4.任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。

当线程池中有任务需要执行时,线程池会判断如果池里的线程数没有占满就会新建线程池进行任务执行,如果线程池中的线程数量已经超过核心线程数,这时候任务就会被放入任务队列中排队等待执行;如果任务队列也满了,并且线程池没有达到最大线程数,就会新建非核心线程来执行任务;如果超过了最大线程数,就会执行饱和策略(拒绝执行)。

追问1:连接池 和 线程池是一个意思么?有什么区别?

不同点

连接池:

  • 连接池是面向数据库连接的
  • 连接池是为了优化数据库连接资源
  • 连接池有点类似在客户端做优化

数据库连接是一项有限的昂贵资源,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的性能低下。

数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由应用程序动态地对池中的连接进行申请、使用和释放。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。

线程池:

  • 线程池是面向后台程序的
  • 线程池是是为了提高内存和CPU效率
  • 线程池有点类似于在服务端做优化

线程池是一次性创建一定数量的线程(应该可以配置初始线程数量的),当用请求过来不用去创建新的线程,直接使用已创建的线程,使用后又放回到线程池中。

避免了频繁创建线程,及销毁线程的系统开销,提高是内存和CPU效率。

相同点

都是事先准备好资源,避免频繁创建和销毁的代价。

面试题2:线程池中核心线程数量大小你是怎么设置的?

分析一般从几个角度考虑:

  • 任务的性质:CPU密集型的任务、IO密集型任务、混合型任务。
  • 任务的优先级:高、中、低
  • 任务执行时间:长、中、短
  • 任务的依赖性:是否依赖其它系统资源,如数据库的连接等。

cpu密集型

尽量减少线程数;比如像加解密,压缩、计算等一系列需要大量耗费 CPU 资源的任务,大部分场景下都是纯 CPU 计算。尽量使用较小的线程池,一般为CPU核心数+1。因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,会造成CPU过度切换。

IO密集型

任务尽量加大线程数,因为io不占用cpu的资源。比如像 MySQL 数据库、文件的读写、网络通信等任务,这类任务不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多时间。可以使用稍大的线程池,一般为CPU核心数 * 2。IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU时间。

混合型

尽量根据实际情况进行拆分,根据运行时间来决定。

可见,线程的平均工作时间所占比例越高,就需要越少的线程;线程的平均等待时间所占比例越高,就需要越多的线程;

追问1:核心线程数量过大或过小会造成什么后果?

当线程池中核心线程数量过大时,线程与线程之间会争取CPU资源,这样就会导致上下文切换。过多的上下文切换会增加线程的执行时间,影响了整体执行的效率;

多线程编程中一般线程的个数都大于CPU核心的个数,而一个CPU核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效的执行,CPU采取的策略是为了每个线程分配时间片并轮转的形式。当一个线程的时间片用完的时候就会重新处于就绪状态让其他线程使用,这个过程就属于一次上下文切换。

当线程池中的核心线程数量过少时,如果统一时间有大量任务需要处理,可能会导致大量任务在任务队列中排队等待执行,甚至会出现队列满了之后任务无法执行的情况,或者大量任务堆积在任务队列导致内存溢出(OOM)。

面试题3:线程池都有哪些状态呀?

线程池的5种状态:RunningShutDownStopTidyingTerminated

  • RUNNING:线程池的初始化状态是RUNNING,能够接收新任务,以及对已添加的任务进行处理。
  • SHUTDOWN:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。 调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
  • STOP:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。 调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
  • TIDYING:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
  • TERMINATED:线程池彻底终止,就变成TERMINATED状态。线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

  当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。 当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。

追问1:什么条件下会进入TERMINATED状态

  • 线程池不是RUNNING状态;
  • 线程池状态不是TIDYING状态或TERMINATED状态;
  • 如果线程池状态是SHUTDOWN并且workerQueue为空;
  • workerCount为0;
  • 设置TIDYING状态成功。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java面试题冲刺第二十五天--并发编程1

    目录 面试题1:简单说下你对线程和进程的理解? 正经回答: 深入追问: 追问1:那进程和线程有哪些区别呢? 面试题2:守护线程和用户线程的区别? 正经回答: 面试题3:什么是线程死锁? 正经回答: 深入追问: 追问1:形成死锁的四个必要条件是什么? 追问2:我们该如何避免死锁? 追问3:死锁避免和死锁预防有啥不同? 总结 面试题1:简单说下你对线程和进程的理解? 正经回答: 进程 一个在内存中运行的应用程序.每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,

  • Java并发编程之详解ConcurrentHashMap类

    前言 由于Java程序员常用的HashMap的操作方法不是同步的,所以在多线程环境下会导致存取操作数据不一致的问题,Map接口的另一个实现类Hashtable 虽然是线程安全的,但是在多线程下执行效率很低.为了解决这个问题,在java 1.5版本中引入了线程安全的集合类ConcurrentMap. java.util.concurrent.ConcurrentMap接口是Java集合类框架提供的线程安全的map,这意味着多线程同时访问它,不会影响map中每一条数据的一致性.ConcurrentM

  • [java并发编程之深入理解]Synchronized的使用

    1.为什么要使用synchronized 在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据.关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile. 2.实现原理 synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性 3.synchronized的三种应

  • Java并发编程之详解CyclicBarrier线程同步

    CyclicBarrier线程同步 java.util.concurrent.CyclicBarrier提供了一种多线程彼此等待的同步机制,可以把它理解成一个障碍,所有先到达这个障碍的线程都将将处于等待状态,直到所有线程都到达这个障碍处,所有线程才能继续执行. 举个例子:CyclicBarrier的同步方式有点像朋友们约好了去旅游,在景点入口处集合,这个景点入口就是一个Barrier障碍,等待大家都到了才一起进入景点游览参观. 进入景点后大家去爬山,有的人爬得快,有的人爬的慢,大家约好了山顶集合

  • Java面试题冲刺第二十四天--并发编程

    目录 面试题1:说一下你对ReentrantLock的理解? CAS: AQS: 追问1:你认为 ReentrantLock 相比 synchronized 都有哪些区别? 面试题2:解释一下公平锁和非公平锁? 面试题3:能详细说一下CAS具体实现原理么? 追问1:那CAS的缺陷有哪些呢? 1.ABA: 2.自旋消耗资源: 3.多变量共享一致性问题: 追问2:讲一下什么是ABA问题?怎么解决? 总结 面试题1:说一下你对ReentrantLock的理解? ReentrantLock是JDK1.5

  • Java面试题冲刺第二十五天--并发编程2

    目录 面试题1:简单说下你对线程和进程的理解? 正经回答: 深入追问: 追问1:那进程和线程有哪些区别呢? 面试题2:守护线程和用户线程的区别? 正经回答: 面试题3:什么是线程死锁? 正经回答: 深入追问: 追问1:形成死锁的四个必要条件是什么? 追问2:我们该如何避免死锁? 追问3:死锁避免和死锁预防有啥不同? 总结 面试题1:简单说下你对线程和进程的理解? 正经回答: 进程 一个在内存中运行的应用程序.每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,

  • Java面试题冲刺第二十五天--并发编程3

    目录 面试题1:你了解线程池么?简单介绍一下. 追问1:连接池 和 线程池是一个意思么?有什么区别? 不同点 面试题2:线程池中核心线程数量大小你是怎么设置的? 追问1:核心线程数量过大或过小会造成什么后果? 面试题3:线程池都有哪些状态呀? 追问1:什么条件下会进入TERMINATED状态 总结 面试题1:你了解线程池么?简单介绍一下. java提供的一个java.util.concurrent.Executor接口的实现用于创建线程池. 线程池是一种多线程处理形式,处理过程中将任务提交到线程

  • Java面试题冲刺第二十五天--实战编程2

    目录 面试题2:怎么理解负载均衡的?你处理负载均衡都有哪些途径? 1.[协议层]http重定向 2.[协议层]DNS轮询 3.[协议层]CDN 4.[协议层]反向代理负载均衡 5.[网络层]IP负载均衡 面试题3:你平时是怎样定位线上问题的? 总结 面试题1:当你发现一条SQL很慢,你的处理思路是什么? 发现Bug 确定Bug不是自己造成的,如果无法确定,不要理会步骤1 向组内宣传"程序里有一个未知Bug,错不在我" 谁响应,谁对Bug负责 没人响应,就要求特定人员配合调试 如果不配合

  • Java面试题冲刺第二十五天--JVM2

    目录 面试题1:简单说一下java的垃圾回收机制. 面试题2:JVM会在什么时候进行GC呢? 追问1:介绍一下不同代空间的垃圾回收机制 追问2:能说一下新生代空间的构成与执行逻辑么? 追问3:说一下发生OOM时,垃圾回收机制的执行流程. 面试题3:Full GC .Major GC和 Minor GC有什么不同 (1)Minor GC / Young GC (2)Old GC (3)Full GC (4)Major GC (5)Mixed GC 总结 面试题1:简单说一下java的垃圾回收机制.

  • Java面试题冲刺第二十六天--实战编程

    目录 面试题1:你们是怎样保存用户密码等敏感数据的? 面试题2:怎么控制用户请求的幂等性的? 1.设置唯一索引:防止新增脏数据 2.token机制:防止页面重复提交 3.悲观锁 4.乐观锁 5.分布式锁 面试题3:你们是如何预防SQL注入问题的? 预防方式: 1.PreparedStatement(简单有效) 2.使用正则表达式过滤传入的参数 3.使用正则表达式过滤传入的URL 总结 面试题1:你们是怎样保存用户密码等敏感数据的? 本题回答参考朱晔的<Java业务开发常见错误100例> 我们知

  • Java面试题冲刺第二十六天--实战编程2

    目录 面试题2:怎么理解负载均衡的?你处理负载均衡都有哪些途径? 1.[协议层]http重定向 2.[协议层]DNS轮询 3.[协议层]CDN 4.[协议层]反向代理负载均衡 5.[网络层]IP负载均衡 面试题3:你平时是怎样定位线上问题的? 总结 面试题1:当你发现一条SQL很慢,你的处理思路是什么? 发现Bug 确定Bug不是自己造成的,如果无法确定,不要理会步骤1 向组内宣传"程序里有一个未知Bug,错不在我" 谁响应,谁对Bug负责 没人响应,就要求特定人员配合调试 如果不配合

  • Java面试题冲刺第十五天--设计模式

    目录 面试题1:面向对象程序设计(OOP)的六大原则分别有哪几个 面试题2:你说一下什么是设计模式 追问1:那你怎么理解高内聚和低耦合? 面试题3:设计模式有哪几种? 追问1:你比较熟悉哪种设计模式?说说原理. 追问2:那你说说适配器模式的原理吧 适配器模式优缺点 总结 面试题1:面向对象程序设计(OOP)的六大原则分别有哪几个 开闭原则(Open Close Principle)及"开放-封闭原则"单一职责原则(Single Responsibility Principle)里氏替换

  • Java面试题冲刺第二十九天--JVM3

    目录 面试题1:如何判断对象是否存活 1.引用计数算法 2.可达性分析算法 面试题2:哪些对象可以作为GC Roots? 面试题3:你了解的对象引用方式都有哪些? 1 强引用 2 软引用 3 弱引用 4 虚引用 总结 面试题1:如何判断对象是否存活 对于判断对象是否存活,主要是两种基本算法,引用计数和可达性分析,目前java主要采用的是可达性分析算法 1.引用计数算法 判断对象是否存活的方式如:在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一:当引用失效时,计数器值就减一:任何

随机推荐