面试题线程池,java多线程面试题

  面试题线程池,java多线程面试题

  如何解决写爬虫IP受阻的问题?立即使用。

  下面是我整理的一些java面试中常见的线程池问题,现在分享给大家。

  (学习视频分享:java教学视频)

  什么是线程池?

  线程池是多线程处理的一种形式,任务提交给线程池,任务的执行由线程池管理。

  如果每个请求都通过创建一个线程来处理,那么服务器的资源将会很快耗尽。使用线程池可以减少创建和销毁线程的数量,并且每个工作线程可以重用来执行多个任务。

  为什么要使用线程池?

  创建和销毁线程的成本很高,可能比处理业务的时间还要长。如此频繁的线程创建和线程销毁,再加上业务工作线程花费的时间,可能会导致系统资源不足。(我们可以去掉创建和销毁线程的过程)

  线程池的作用是什么?

  线程池的作用是限制系统中执行线程的数量。

  1.提高效率。创建一定数量的线程,并将它们放入池中。需要的时候从泳池里拿一个。这比在需要时创建线程对象要快得多。

  2.管理方便。您可以编写线程池管理代码来管理池中的相同线程。例如,当程序启动时,它创建100个线程,每当有请求时,它就分配一个线程工作。如果只有101个并发请求,额外的请求可以排队,以避免由无休止的线程创建导致的系统崩溃。

  说几个常见的线程池和使用场景。

  1、新线程执行程序

  创建一个单线程线程池,该线程池将只使用唯一的工作线程来执行任务,并确保所有任务都按照指定的顺序(FIFO、LIFO、priority)执行。

  2、新固定线程池

  创建一个固定长度的线程池来控制并发线程的最大数量,多余的线程将在队列中等待。

  3、新缓存线程池

  创建一个可缓存的线程池。如果线程池的长度超过了处理需要,可以灵活地回收空闲线程。如果没有回收,可以创建一个新线程。

  4、新调度线程池

  创建一个固定长度的线程池来支持计划的和定期的任务执行。

  线程池中的几个重要参数

  CorePoolSize是线程池中的核心线程数。这些核心线程只有在没用的时候才会被回收。

  MaximumPoolSize是线程池中可以容纳的最大线程数。

  KeepAliveTime是线程池中除了核心线程之外可以保持的最长时间,因为在线程池中,除了核心线程,即使没有任务也不能清除,其余的都有生存期,也就是说非核心线程可以保持的最长空闲时间。

  Util是计算这个时间的单位。

  工作队列是等待队列。任务可以存储在任务队列中,等待执行。实施FIFIO原则(先进先出)。

  (分享更多相关面试问题:java面试问答)

  ThreadFactory是创建线程的线程工厂。

  Handler,是一种拒绝策略。任务满了之后我们可以拒绝执行某些任务。

  谈线程池的拒绝策略

  当请求任务不断到来,此时系统无法处理时,我们需要采取的策略就是拒绝服务。RejectedExecutionHandler接口提供了拒绝任务处理的自定义方法的机会。ThreadPoolExecutor已经包含了四种处理策略。

  AbortPolicy policy:这个策略会直接抛出异常,阻止系统正常工作。

  CallerRunsPolicy:只要线程池没有关闭,这个策略就直接在调用者的线程中运行当前丢弃的任务。

  DiscardOleddestPolicy策略:该策略将丢弃最旧的请求,即要执行的任务,并尝试再次提交当前任务。

  DiscardPolicy策略:此策略会自动丢弃无法处理的任务,并且根本不会处理这些任务。

  除了JDK默认提供的四种拒绝策略外,我们还可以根据自己的业务需求定制拒绝策略。定制的方式很简单,直接实现RejectedExecutionHandler接口即可。

  执行和提交的区别?

  在前面的解释中,我们使用了execute方法来执行任务。除了execute方法,还有一个submit方法也可以执行我们提交的任务。

  这两种方法有什么区别?它们适用于什么场景?我们来做一个简单的分析。

  Execute适用于不需要关注返回值,只需要把线程扔进线程池执行的场景。

  submit方法适用于需要注意返回值的场景。

  五个线程池的使用场景

  NewSingleThreadExecutor:单线程线程池,可用于需要顺序执行,而只有一个线程在执行的场景。

  NewFixedThreadPool:一个固定大小的线程池,当并发压力已知时,可以用来限制线程的数量。

  NewCachedThreadPool:可以无限扩展的线程池,比较适合处理执行时间相对较短的任务。

  NewScheduledThreadPool:一个可以延迟和计时启动的线程池。它适用于需要多个后台线程来执行定期任务的情况。

  NewWorkStealingPool:具有多个任务队列的线程池,可以减少连接数,用当前可用的cpu号创建线程并行执行。

  线程池的关闭

  关闭线程池可以通过调用shutdownNow和shutdown方法来实现。

  ShutdownNow:向所有正在执行的任务发出interrupt(),停止执行,取消所有尚未开始的任务,返回尚未开始的任务列表。

  Shutdown:当我们调用shutdown时,线程池将不再接受新任务,但不会强制终止已提交或正在执行的任务。

  初始化线程池时线程号的选择

  如果任务是IO密集型的,一般线程数应该设置为CPU数的2倍以上,这样才能充分利用CPU资源。

  如果任务是CPU密集型的,一般线程数只需要按CPU加1来设置,更多的线程只能增加上下文切换,而不能增加CPU利用率。

  以上只是一个基本思路。如果真的需要精确控制,还是需要观察线程池中线程的数量,以及上线后队列的情况。

  线程有哪几种工作队列?

  1、ArrayBlockingQueue

  是基于数组结构的有界阻塞队列,按照FIFO(先进先出)原则对元素进行排序。

  2、LinkedBlockingQueue

  基于链表结构的阻塞队列,按照FIFO(先进先出)对元素进行排序,其吞吐量通常高于ArrayBlockingQueue。工厂方法Executors.newFixedThreadPool()使用这个队列。

  3、同步队列

  不存储元素的阻塞队列。每个插入操作都必须等到另一个线程调用移除操作,否则插入操作将始终被阻塞,吞吐量通常高于静态工厂方法Executors.newCachedThreadPool使用的LinkedBlockingQueue

  4、优先级阻塞队列

  具有优先级的无限阻塞队列。

  相关课程推荐:java入门教程以上是java面试线程池的详细介绍。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: