【JAVA中级篇】线程池
上一篇文章已经介绍了线程的基本概念以及线程相关的API,下面来看一下线程池
一、线程池框架
1、线程池的优点
- 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
- 能有效控制线程池的最大并发数,避免大量线程之间因互相抢夺系统资源而导致的阻塞现象。
- 能够对线程进行简单的管理,并提供定时执行以及指向间隔循环执行等功能。
2、JAVA中相关类
Executor是一个顶层接口,它里面只声明了一个方法execute(Runnable)
ExecutorService接口继承了Executor接口,并且声明了一些方法:submit、invokeAll、invokeAny以及shutDown等AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法
ThreadPoolExecutor接口继承了AbstractExecutorService这个类,并且实现了这些重要方法:execute() 、shutdown()、shutdownNow()
Executors提供了大量的static方法,来创建各种特性的线程池(基于ThreadPoolExecutor的构造方法)、大量的callable方法和创建ThreadFactory的方法
ThreadPoolExecutor的重要属性
private final BlockingQueue<Runnable> workQueue;//任务缓存队列,用来存放等待执行的任务private final ReentrantLock mainLock = new ReentrantLock();//线程池的主要状态锁,对线程池状态(比如线程池大小、runState等)的改变都要使用这个锁private final HashSet<Worker> workers = new HashSet<Worker>();//用来存放工作集private final Condition termination = mainLock.newCondition();//private int largestPoolSize;//用来记录线程池中曾经出现过的最大线程数private long completedTaskCount;//用来记录已经执行完毕的任务个数private volatile ThreadFactory threadFactory;//线程工厂,用来创建线程private volatile RejectedExecutionHandler handler;//任务拒绝策略private volatile long keepAliveTime;//线程存活时间 private volatile boolean allowCoreThreadTimeOut;//是否允许为核心线程设置存活时间private volatile int corePoolSize;//核心池的大小(即线程池中的线程数目大于这个参数时,提交的任务会被放进任务缓存队列)private volatile int maximumPoolSize;//线程池最大能容忍的线程数private static final RejectedExecutionHandler defaultHandler =new AbortPolicy();//默认的任务拒绝策略private static final RuntimePermission shutdownPerm =new RuntimePermission("modifyThread");
这里要重点解释一下corePoolSize、maximumPoolSize、largestPoolSize三个变量。
corePoolSize在很多地方被翻译成核心池大小,其实我的理解这个就是线程池的大小。举个简单的例子:
假如有一个工厂,工厂里面有10个工人,每个工人同时只能做一件任务。
因此只要当10个工人中有工人是空闲的,来了任务就分配给空闲的工人做;
当10个工人都有任务在做时,如果还来了任务,就把任务进行排队等待;
如果说新任务数目增长的速度远远大于工人做任务的速度,那么此时工厂主管可能会想补救措施,比如重新招4个临时工人进来;
然后就将任务也分配给这4个临时工人做;
如果说着14个工人做任务的速度还是不够,此时工厂主管可能就要考虑不再接收新的任务或者抛弃前面的一些任务了。
当这14个工人当中有人空闲时,而新任务增长的速度又比较缓慢,工厂主管可能就考虑辞掉4个临时工了,只保持原来的10个工人,毕竟请额外的工人是要花钱的。
这个例子中的corePoolSize就是10,而maximumPoolSize就是14(10+4)。
也就是说corePoolSize就是线程池大小,maximumPoolSize在我看来是线程池的一种补救措施,即任务量突然过大时的一种补救措施。
不过为了方便理解,在本文后面还是将corePoolSize翻译成核心池大小。
largestPoolSize只是一个用来起记录作用的变量,用来记录线程池中曾经有过的最大线程数目,跟线程池的容量没有任何关系。
重要方法
execute
public void execute(Runnable command) {if (command == null)throw new NullPointerException();int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);}
3、线程池的分类
newFixedThreadPool
newWorkStealingPool
newSingleThreadExecutor
newCachedThreadPool
newSingleThreadScheduledExecutor
newScheduledThreadPool
重点是ThreadPoolExecutor的代码、还需要理解线程池状态、任务的执行、线程池中的线程初始化、任务缓存队列及排队策略、任务拒绝策略、线程池的关闭、线程池容量的动态调整
简单使用Demo
package com.demo;import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPool { private int threadCount = 10;private int threadpoolCount = 3;public static void main(String[] args) {new ThreadPool().threadPoolControl();}public void threadPoolControl() { ThreadObject[] et = new ThreadObject[threadCount]; ExecutorService service = Executors.newFixedThreadPool(threadpoolCount);Collection<ThreadObject> c = new ArrayList<ThreadObject>();for (int i = 0; i < threadCount; i++) { et[i] = new ThreadObject(); c.add(et[i]);}try {service.invokeAll(c);service.shutdown();} catch (InterruptedException e) {e.printStackTrace();}}class ThreadObject implements Callable<Object>{ public Object call() throws Exception {System.out.println("当前线程:"+Thread.currentThread().getName()+",线程对象:"+this);return null;}}
}
【JAVA中级篇】线程池相关推荐
- 万字图文 | 学会Java中的线程池,这一篇也许就够了!
来源:一枝花算不算浪漫 线程池原理思维导图.png 前言 Java中的线程池已经不是什么神秘的技术了,相信在看的读者在项目中也都有使用过.关于线程池的文章也是数不胜数,我们站在巨人的肩膀上来再次梳理一 ...
- Java并发编程——线程池的使用
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...
- Java多线程之线程池详解
Java多线程之线程池详解 目录: 线程池使用及优势 线程池3个常用方式 线程池7大参数深入介绍 线程池底层工作原理 1. 线程池使用及优势 线程池做的工作主要是控制运行的线程的数量,处理过程中将任务 ...
- [转]new Thread的弊端及Java四种线程池的使用
介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new ...
- Java 四种线程池
原文 介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下n ...
- java并发包线程池原理分析锁的深度化
java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素 ...
- java中的线程池有哪些,分别有什么作用?
阅读完本篇文章会知道如下三点: 1.进程-线程简单介绍 2.java的线程池是什么,有哪些类型,作用分别是什么 3.使用线程池的优点 1.进程-线程的简单介绍 进程 什么是进程呢? 进程是计算机中的程 ...
- java多线程之线程池简介
前言 池化技术已经屡见不鲜了,比如数据库连接池,大家的项目中应该也用到了线程池.池化技术的好处:降低资源的消耗,提高响应速度,提高线程的可管理性.本篇主要是和大家一起分析下线程池的架构和它的工作流程. ...
- Java手写线程池-第一代(原创)
个人简介 作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门. 文章目录 个人简介 Java手写线程池(第一代) ...
- Java 并发编程 -- 线程池源码实战
一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...
最新文章
- python3对比python2的更新点
- ASP.NET Core 2 学习笔记(七)路由
- 工厂模式、策略者模式、责任链模式综合应用
- xenserver下的SR,VDI,VBD
- python calu_Python基本数据类型
- spring整合mybatis是如何配置事务的?
- LeetCode 421. 数组中两个数的最大异或值
- Ocelot简易教程(二)之快速开始2
- java url authority,Java如何解析url,包括自定义schema的url
- 用心整理,尽量最全,一套目标检测、卷积神经网络和OpenCV学习资料(教程/PPT/代码)...
- threejs引擎中 环境光线与管道流动
- 为VIP解决问题时写的源码
- SPOJ SUBST1 New Distinct Substrings(后缀数组 本质不同子串个数)题解
- vue项目中引入外部字体(超详细)
- Adobe Photoshop CC2014 安装过程
- 软件著作权登记申请容易通过吗?软著申请成功率高吗?
- C++三种创建对象的方法区别
- 【STM32笔记】HAL库低功耗模式配置(ADC唤醒无法使用、低功耗模式无法烧录解决方案)
- Mathorcup数学建模竞赛第六届-【妈妈杯】B题:车位分布的优化设计与评价(附一等奖获奖论文和matlab代码)
- 用大数据提升食品安全