栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

线程池的基本概念

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程池的基本概念

文章目录
  • 线程池
    • 前言
    • 线程池的类结构图
    • 线程池状态
    • ThreadPoolExecutor构造方法
    • 使用newFixedThreadPool方法给线程池创建固定线程数
    • 提交任务方法submit
    • 关闭线程池方法shutdown
    • 创建多线程的几个方法
      • 直接继承Thread
      • 实现Runnable接口
      • 实现Callable接口
    • jdk1.8新增线程池

线程池 前言

平时讨论多线程处理,一定会说使用线程池,那为什么要使用线程池呢?其实,这个问题也可以反过来思考一下,如果不使用线程池会怎么样?

当需要多线程并发执行任务时,只能不断的通过new Thread创建线程,每创建一个线程都需要在堆上分配内存空间,同时需要分配虚拟机栈,本地方法栈,程序计数器等线程私有的内存空间,当这个线程对象被可达性分析算法标记为不可用时,被GC回收,这样频繁的创建和回收需要大量的额外开销。再者说,JVM的内存资源是有限的,如果系统中大量的创建线程对象,JVM很可能直接抛出OutOfMemoryError异常,还有大量的线程去竞争CPU会产生其他的性能开销,更多的线程反而会降低性能,所以必须要限制线程数。

既然不使用线程池会有那么多问题,我们来看一下使用线程池有哪些好处:

1.使用线程池可以复用池中的线索,不需要每次都创建新线程,减少创建和销毁线程的开销。

2.同时,线程池具有队列缓冲策略,拒绝机制和动态管理线程个数,特定的线程池还具有定时执行,周期执行功能,比较重要的一点是线程池可以实现线程环境的隔离,例如分别定义支付功能相关线程池和优惠券功能相关线程池,当其中一个运行有问题时不会影响另一个。

一个线程池里面有多个线程,因此我们后续都是用线程池对象的方法进行多线程操作的,这样我们只针对线程池对象就行了,不必再针对线程对象了,因此我们就不用频繁的创建销毁线程了。

线程池的类结构图

如下图:

线程池状态

Running:线程池运行状态

Shutdown状态:线程池不会再接收新的任务,但会处理阻塞队列剩余任务

Stop状态:会中断正在执行的任务,并抛弃阻塞队列任务

Tidying状态:任务全部执行完毕,活动线程为0即将进入终结

Terminated状态:终结状态。

ThreadPoolExecutor构造方法
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

corePoolSize 核心线程数目,最多保留的线程数

maximumPoolSize 最大线程数目

keepAliveTime 生存时间-针对救急线程

unit 时间单位-针对救急线程

workQueue 阻塞队列

threadFactory 线程工厂-可以为线程创建时起个好名字

handler 拒绝策略

最大线程数=核心线程数+救急线程数,其中核心线程不会消失永远存在,而救急线程是会消失的。

使用newFixedThreadPool方法给线程池创建固定线程数

newFixedThreadPool方法可以在线程池里面创建固定的线程个数,如下图:

当我们调用我们的线程池执行一个任务的时候,线程池会调用它里面的线程此任务,如下图:

提交任务方法submit
//执行任务
void execute(Runnable command);

//提交任务task,用返回值Future获得任务执行结果
 Future submit(Callable task);

//提交tasks中所有任务
 List> invokeAll(Collection> tasks)
    throws InterruptedException;

//提交tasks中所有任务,带超时时间
 List> invokeAll(Collection> tasks,
                             long timeout,TimeUnit unit)
    throws InterruptedException;

//提交tasks中所有任务,哪个任务先成功执行完毕,返回此任务执行结果,其他任务取消
 T invokeAny(Collection> tasks)
    throws InterruptedException;

//提交tasks中所有任务,哪个任务先成功执行完毕,返回此任务执行结果,其他任务取消,带超时时间
 T invokeAny(Collection<>? extends Callable> tasks,
               long timeout,TimeUnit unit)
    throws InterruptedException;

当我们使用submit给线程池提交任务的时候,线程池会用它里面的不同的线程去并发执行这些任务,如下图:

submit方法提交任务的时候,有两种类型的参数,一种是Callable线程任务,这种任务有返回值并且可以内部抛异常,另外一种是Runnable线程任务,这种任务没有返回值并且不可以在内部抛异常。但是Callable和Runnable对象都属于是多线程任务对象。Callable线程对象对应的线程方法是call方法,而Runnable线程对象对应的方法是run方法。

对于任务来讲,只要它一提交到线程池里面,它就会被自动的用线程池里面的线程执行了。

使用submit提交的线程任务,一般会在下面的普通代码执行之后执行,如下图:

关闭线程池方法shutdown
void shutdown();


List shutdownNow();


创建多线程的几个方法 直接继承Thread

实现Runnable接口

实现Callable接口

jdk1.8新增线程池

使用偷窃线程池的时候,线程池中的每个线程都有一个任务队列,线程之前可以互相帮助,如果一个线程的工作已经干完了,发现另外一个线程的工作还没有干完,那么这个线程会去帮另外一个线程工作。这个线程池非常适合于耗时较长的任务。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/919485.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号