欢迎光临散文网 会员登陆 & 注册

后端 | Java | 线程池

2023-06-17 23:07 作者:朵宝特工007  | 我要投稿

笔记来源:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程

一、线程池概述

概念:

  • 线程池就是一个可以复用线程的技术。

不适用线程池的问题:

  • 如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能

工作原理:

  • 线程池通过提供固定的核心线程(工作线程WorkThread)任务队列(WorkQueue)来工作,当核心线程都在忙时,新来的任务进入任务队列,等待核心线程的处理。


二、线程池实现的API、参数说明

JDK5.0起提供了代表线程池的接口,ExecutorService

ExcutorService常用方法:

  • void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable任务。

  • Future<T> submit(Callable<T> task):执行任务,返回未来任务对象获取线程结果,一般拿来执行Callable任务。

  • void submit():等任务执行完毕后关闭线程池。

  • List<Runnable> shutdownNow():立刻关闭,停止正在执行的任务,并返回队列中未执行的任务。

如何得到一个线程池对象:

  • 方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

    • ThreadPoolExecutor构造器的参数说明:

      • 指定线程池的线程数量(核心线程):corePoolSize,不能小于0。

      • 指定线程池可支持的最大线程数:maximumPoolSize,最大数量>=核心线程数量。

      • 指定临时线程的最大存活时间:keepAliveTime,不能小于0。

      • 指定存活时间的单位(秒、分、时、天):unit,时间单位。

      • 指定任务队列:workQueue,不能为null。

      • 指定用哪个线程工厂创建线程:threadFactory,不能为null。

      • 指定线程忙,任务满时,新任务来了怎么办:handler,不能为null。

  • 方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。

    • Executors的底层也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。

    • Executors得到线程池对象的常用方法:

      • public static ExecutorService newCachedThreadPool():线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了一段时间则会被回收掉。

      • public static ExecutorService newFixedThreadPool(int nThreads):创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。

      • public static ExecutorService newStringThreadExecutor():创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。

      • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。

  • Executors使用可能存在的陷阱

    • 大型并发系统环境中使用Executors如果不注意可能会出现系统风险。

    • 可能会出现OOM错误(Java.lang.OutOfMemoryError)。


三、线程池处理Runnable任务

ThreadPoolExecutor创建线程池对象:

  • 新任务拒绝策略

    • ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,是默认的策略。

    • ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常,这是不推荐的做法。

    • ThreadPoolExecutor.DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中。

    • ThreadPoolExecutor.CallerRunsPolicy:由主线程负责调用任务的run()方法从而绕过线程池直接执行。

给一个任务给线程池处理:


四、线程池处理Callable任务


五、线程池常见面试题

  • 临时线程什么时候创建?

    • 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

  • 什么时候会开始拒绝任务?

    • 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。



后端 | Java | 线程池的评论 (共 条)

分享到微博请遵守国家法律