JAVA中的线程池

———————–本文参考《JAVA并发编程的艺术》和JDK1.8。—————

JAVA中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行的任务的程序都可以使用线程池。
->《JAVA并发编程的艺术》

1.线程池的好处

  • 降低线程创建和销毁造成的资源损耗。
  • 提高响应速度:任务到达时,可以装载到线程中执行,而不必等到线程创建完毕。
  • 提高线程的可管理性:使用线程池可以进行统一分配、调优和监控。
  • 控制最大并发数,避免阻塞。

2.线程池的实现原理

当使用者向线程池提交一个任务之后,线程池的处理流程如下:

这里写图片描述

这里我来解释一下:

在线程池中,存在一个内部的核心线程池,核心线程池中的线程是任务执行的核心干将,既然他们是“干将”那么我们有任务肯定有限将任务交给这些线程。当任务到达,我们先去查询核心线程池中的线程(“干将”)是否都有任务在身并且“干将”的数目达没达到指定数目,如果核心线程的数目未到指定数目,那么就创建新的核心线程来执行任务;如果不满足上述条件,再去判断阻塞队列是否已满,如果未满,那么将任务打入队列;如果队列满了,那么去判断“小兵”(线程池中的非核心线程)是否数目足够了,如果没有则创建线程,如果够了那么执行一定的策略。

ThreadPoolExecutor采取上述步骤的整体设计思路,是为了在执行execute()方法时,尽可能的避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。在ThreadPoolExecutor完成预热之后(即当前运行的线程数大于等于corePoolSize值),几乎所有的executer()方法调用都是调用步骤2,而步骤2不需要获取全局锁。

从源码简单看线程池的工作原理:

线程池创建线程时,会将线程封装成工作线程worker,worker在执行完任务后,还会循环获取工作队列内的任务来执行。

3.线程池的使用

⑴:线程池的创建

这里我们先简单点了解一下关于线程池内部的一些主要参数,具体的分析以后会在源码解析里面详细解释一下。

①corePoolSize:线程池的基本大小,即核心干将的数量上限。当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建该类线程,等到执行的任务书大于线程池基本大小时就不在创建。

②runnableTaskQueue:任务队列,用于保存等待执行的任务的阻塞队列,又分为基于链表结构的队列,基于数组结构的队列,具有优先级的无限阻塞队列等。

③maxinumPoolSize:线程池的最大数量,也就是线程池可以创建的线程的最大数,如果使用了无界的任务队列这个参数就没有什么效果。

④ThreadFactory:用于设置创建线程的工厂。

⑤RejectedExecutionHandler:饱和策略,线程池不能承载任务时采用的处理多余任务的方式,有抛出异常、丢弃队列里最近的一个任务并执行当前任务、不处理并且丢弃任务等策略。

⑵:向线程池提交任务

可以使用2个方法,execute()和submit()。

execute()用于提交无返回值的任务,submit()用于提交有返回值的任务。

⑶:关闭线程池

2个方法,shutdown()和shutdownNown()。它们的普遍原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程。

shutdown()会中断所有没有正在执行任务的线程,shutdownNown()会关闭所有线程,而不会管任务是否执行完毕。

4.线程池的监控

监控线程池的时候可以使用下面几个属性:

1.taskCount:线程需要执行的任务数目。

2.completedTasdCount:线程池在运行过程中已完成的任务数量,小于或者等于taskCount。

3.targestPoolSize:线程池中曾经存在的线程的最大数量。通过该属性可以知道线程池是否满过。

4.getPoolSize:线程池内的线程数量。如果线程池不销毁,线程池里的线程不会自动销毁,所以该属性只增不减

5.getActiveCount:获取活动的线程数。

总结:本文只是简要介绍了一下JAVA中的线程池有关概念,接下来的博文中我会结合实际Demo着重介绍线程池具体的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池的参数包括以下7个: 1. corePoolSize:线程池的基本大小,即在没有任务需要执行的时候线程池的大小。 2. maximumPoolSize:线程池最大的大小,即线程池允许的最大线程数。 3. keepAliveTime:线程池线程空闲后,保持存活的时间。 4. unit:keepAliveTime的时间单位。 5. workQueue:任务队列,用于保存等待执行的任务的阻塞队列。 6. threadFactory:线程工厂,用于创建新线程。 7. handler:拒绝策略,用于当任务队列已满,且线程池线程数达到maximumPoolSize时,如何拒绝新任务的策略。 下面是一个示例代码,展示了如何使用Java线程池参数: ```java import java.util.concurrent.*; public class ThreadPoolDemo { public static void main(String[] args) { // 创建一个线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // corePoolSize 4, // maximumPoolSize 60, // keepAliveTime TimeUnit.SECONDS, // unit new ArrayBlockingQueue<Runnable>(4), // workQueue Executors.defaultThreadFactory(), // threadFactory new ThreadPoolExecutor.AbortPolicy() // handler ); // 提交任务 for (int i = 0; i < 10; i++) { executor.execute(new Task(i)); } // 关闭线程池 executor.shutdown(); } static class Task implements Runnable { private int num; public Task(int num) { this.num = num; } @Override public void run() { System.out.println("正在执行task " + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("task " + num + "执行完毕"); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值