1 线程池的创建

ThreadPoolExecutor有以下四个构造方法

  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
  • ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
这里面需要几个参数
 
1  corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。
 
2  workQueue(任务队列) : 用于保存等待执行的任务的阻塞队列。可以选择以下几个阻塞队列:
  • ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,按FIFO原则进行排序
  • LinkedBlockingQueue:一个基于链表结构的阻塞队列,吞吐量高于ArrayBlockingQueue。静态工厂方法Excutors.newFixedThreadPool()使用了这个队列
  • SynchronousQueue: 一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量高于LinkedBlockingQueue,静态工厂方法Excutors.newCachedThreadPool()使用了这个队列
  • PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
3  maximumPoolSize(线程池最大数量):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是,如果使用了无界的任务队列这个参数就没用了。
4 threadFactory(线程工厂):可以通过线程工厂为每个创建出来的线程设置更有意义的名字,如开源框架guava
5 RejectedExecutionHandler (饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略还处理新提交的任务。它可以有如下四个选项:
  • AbortPolicy:直接抛出异常,默认情况下采用这种策略
  • CallerRunsPolicy:只用调用者所在线程来运行任务
  • DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
  • DiscardPolicy:不处理,丢弃掉
    更多的时候,我们应该通过实现RejectedExecutionHandler 接口来自定义策略,比如记录日志或持久化存储等。
6 keepAliveTime(线程活动时间):线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程利用率。
 
7 TimeUnit(线程活动时间的单位):可选的单位有天(Days)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)。
 
 

2 提交任务

 
可以使用execute和submit两个方法向线程池提交任务
 
(1)execute方法用于提交不需要返回值的任务,利用这种方式提交的任务无法得知是否正常执行
(2) submit方法用于提交一个任务并带有返回值,这个方法将返回一个Future类型对象。可以通过这个返回对象判断任务是否执行成功,并且可以通过future.get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成。
Future<?> future=threadPoolExecutor.submit(futureTask);
Object value=future.get();

3 关闭线程池

 
可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。他们的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无响应中断的任务可能永远无法停止。但是他们存在一定的区别,shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有正在执行或暂停任务的线程,并返回等待执行任务的列表,而shutdown只是将线程池的状态设置成SHUTDOWN状态,然后中断所有正在执行的任务。
 
只要调用了这两个关闭方法的一个,isShutdown就会返回true。当所有的任务都关闭后,才表示线程池关闭成功,这是调用isTerminated方法会返回true。至于应该调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown方法来关闭线程池,如果任务不一定执行完,则可以调用shutdownNow方法。
 

4 合理配置线程池

要想合理地配置线程池,首先要分析任务特性
  • 任务的性质:CPU密集型任务、IO密集型任务和混合型任务。
  • 任务的优先级:高、中和低。
  • 任务的执行时间:长、中和短。
  • 任务的依赖性:是否依赖其他系统资源,如数据库连接。
性质不同的任务可以用不同规模的线程池分开处理。CPU密集型任务应该配置尽可能少的线程,如配置N+1个线程,N位CPU的个数。而IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如2*N。混合型任务,如果可以拆分,将其拆分成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐量将高于串行执行的吞吐量
优先级不同的任务可以交给优先级队列PriorityBlcokingQueue来处理。
执行时间不同的任务可以交给不同规模的线程池来处理。
依赖数据库的任务,因此线程提交SQL后需要等待数据库返回结果,等待的时间越长,则CPU空闲时间越长,那么线程数应该设置的越大,这样能更好滴利用CPU。

Java线程池——ThreadPoolExecutor的使用的更多相关文章

  1. Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  2. Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  3. Java线程池ThreadPoolExecutor使用和分析(一)

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  4. Java线程池ThreadPoolExecutor类源码分析

    前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...

  5. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  6. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  7. Java 线程池(ThreadPoolExecutor)原理解析

    在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...

  8. Java线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  9. 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue

    从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.ThreadPoolExecutor 就是这样的线程池.以下是我的学习过程. 首先是构 ...

  10. java线程池ThreadPoolExecutor的使用

    package s.b.foo.caze.thread; import java.io.Serializable; import java.util.concurrent.ArrayBlockingQ ...

随机推荐

  1. jquery stop(true,false)的意思

    stop 是jQuery中用于控制页面动画效果的方法.运行之后立刻结束当前页面上的动画效果.stop在新版jQuery中添加了2个参数:第一个参数的意思是是否清空动画序列,也就是stop的是当前元素的 ...

  2. NVIDIA GTC照片

    这次的NVIDIA GPU Technology Conference 2014在美国San Jose(就是俗称的硅谷了)举办. 去美国的飞机上10个小时反正是睡不着,电影还是挺好看的. 美联航的早餐 ...

  3. CXF动态调用wsdl接口

    1.application.properties文件中配置接口url 2.工具类 package com.vulnverify.core.utils; import java.io.IOExcepti ...

  4. linux命令之进程管理命令

    1.ps:查看进程 该命令用于列出命令执行时刻的进程快照,如果想要动态的显示进程信息,可以使用top命令. 参数 说明 a(常用) 显示与终端相关的所有进程,包含每个进程的完整路径 x(常用) 显示与 ...

  5. linux命令提示符[root@localhost ~]#详解

    [root@localhost ~]#   1. @之前代表当前登录用户 在Linux中管理员用户是root,还有一些普通用户: 在此例中,root代表当前登录用户   2. @之后代表当前计算机主机 ...

  6. mycat 1.6.6.1安装以及配置docker 安装mysql 5.7.24 双主多从读写分离主主切换

    mycat和mysql的高可用参考如下两个图 简介:应用程序仅需要连接HAproxy或者mycat,后端服务器的读写分离由mycat进行控制,后端服务器数据的同步由MySQL主从同步进行控制. 服务器 ...

  7. 模块sys, os, glob, pickle, subprocess常见用法

    参考python常用标准库 http://blog.51cto.com/lizhenliang/1872538 一. sys   1. sys.argv 脚本名1.py, 命令行中执行python 1 ...

  8. webpack中设置jquery为全局对象

    通过npm安装jquery npm install jquery -D 然后配置webpack-config.js plugins: [ new webpack.ProvidePlugin({ $: ...

  9. 使用Avd 调试慢的解决方案

         AVD 太慢了,不仅启动,而且运行慢.以致于要用手机去调.你觉得这样方便吗?     如果没有一个简单快速的开发调试环境,把时间都浪费在启动,调试及等待上,那是对生命的浪费.   必要条件: ...

  10. 虚拟立方体调用非共享维度的时候需要指定cubeName,否则Schema无效

    但是,即使把非共享维度放上去,会出现一种情况. 一旦放入资产负债的非公共维度进去后,报表的度量值只能出现资产负债的度量值,不能出现损益的度量值了!