1. websphere线程池在哪设置
主界面里有数据源设置,里边有线程池的设置大小堆栈等信息
2. 线程池之ThreadPoolExecutor使用
ThreadPoolExecutor提供了四个构造方法:
我们以最后一个构造方法(参数最多的那个),对其参数进行解释:
如果对这些参数作用有疑惑的请看 ThreadPoolExecutor概述 。
知道了各个参数的作用后,我们开始构造符合我们期待的线程池。首先看JDK给我们预定义的几种线程池:
适用场景:可用于Web服务瞬时削峰,但需注意长时间持续高峰情况造成的队列阻塞。
适用场景:快速处理大量耗时较短的任务,如Netty的NIO接受请求时,可使用CachedThreadPool。
咋一瞅,不就是newFixedThreadPool(1)吗?定眼一看,这里多了一层包装,这一层有什么用呢,写个dome来解释一下:
对比可以看出,FixedThreadPool可以向下转型为ThreadPoolExecutor,并对其线程池进行配置,而SingleThreadExecutor被包装后,无法成功向下转型。 因此,SingleThreadExecutor被定以后,无法修改,做到了真正的Single。
newScheledThreadPool调用的是ScheledThreadPoolExecutor的构造方法,而ScheledThreadPoolExecutor继承了ThreadPoolExecutor,构造是还是调用了其父类的构造方法。
对于ScheledThreadPool本文不做描述,其特性请关注后续篇章。
以下是自定义线程池,使用了有界队列,自定义ThreadFactory和拒绝策略的demo:
输出结果如下:
其中线程线程1-4先占满了核心线程和最大线程数量,然后4、5线程进入等待队列,7-10线程被直接忽略拒绝执行,等1-4线程中有线程执行完后通知4、5线程继续执行。
多线程系列目录(不断更新中):
线程启动原理
线程中断机制
多线程实现方式
FutureTask实现原理
线程池之ThreadPoolExecutor概述
线程池之ThreadPoolExecutor使用
线程池之ThreadPoolExecutor状态控制
线程池之ThreadPoolExecutor执行原理
线程池之ScheledThreadPoolExecutor概述
线程池的优雅关闭实践
3. 什么是线程池,如何使用,为什么要用
线程池,thread pool,是一种线程使用模式,线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。
功能:应用程序可以有多个线程,这些线程在休眠状态中需要耗费大量时间来等待事件发生。其他线程可能进入睡眠状态,并且仅定期被唤醒以轮循更改或更新状态信息,然后再次进入休眠状态。
为了简化对这些线程的管理,.NET框架为每个进程提供了一个线程池,一个线程池有若干个等待操作状态,当一个等待操作完成时,线程池中的辅助线程会执行回调函数。线程池中的线程由系统管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
(3)线程池web扩展阅读:
应用范围
1、需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
2、对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
3、接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,并出现"OutOfMemory"的错误。
4. 线程池企业级常规使用实例
多线程在学校的时候其实用的非常少,甚至几乎用不到,但是在公司是不一样的,用的非常多,毕竟用户数据量十分的大,曾经实习我在一个项目里面做过一个数据处理,是计算这人和人之间的关系度,从而推出哪几个人的亲密度达到要求,如果不用多线程,要把这一批数据计算完,那么是需要大概一年时间,后来把时间缩短到了8天,降低了两个数量级。
1、我一般是这样用线程池的,首先建立一个池子,当然有时候有现成的池子给你用,看业务是自己创建还是用公共的。
private static final ExecutorService commentExecutor =new ThreadPoolExecutor(20, 20, 1L,
TimeUnit.MINUTES, new ArrayBlockingQueue<>(30), r ->new Thread(r,"comment")); //新建立一个池子,看业务哈,一般这样是可以的,各个参数这里不展开说,后面会解释的,看业务设计参数值;
2、然后往池子里面提任务
List<T> commentInfos = Lists.newCopyOnWriteArrayList(); //一般情况下ArrayList就可以了,这是用guava的
commentExecutor.submit(() -> {
try {
commentInfos.add(buildComment(reqParam));
}catch (Exception e) {
logger.info("buildComment error", e);
}
})
buildComment(reqParam) 这个是执行任务的函数,计算完后结果放到了commentInfos 集合中;
如果是批量计算型任务,而且事先能知道批量数,可以结合CountDownLatch使用,目的可以通过它来控制所有线程计算完后再往下走;
也是比较常用的;
3、CountDownLatch 结合使用
try {
final CountDownLatch latch =new CountDownLatch(reqParam.getProctNos().size()); //事先获取到批次
reqParam.getProctNos().forEach(p -> //遍历
commentExecutor.submit(() -> { //每一个批次提交到池子里面
try {
commentInfos.add(buildComment(p,reqParam)); //开始运算,运算的结果放到commentInfos
}catch (Exception e) {
logger.info("buildComment error", e);
}finally {
latch.countDown(); //每个线程完成就释放掉一个latch
}
})
);
latch.await(); //等待所有的latch释放掉,也就是每一个线程都执行完成
}catch (Exception e) {
logger.error("异常", e);
return WebResponse.fail(e.getMessage());
}finally {
logger.info("结果 commentInfos:{},计算耗时:{}", JsonUtil.encode(commentInfos), stopwatch.elapsed(TimeUnit.MILLISECONDS));
}
可能没用过线程池的小伙伴第一次看有点不明白,没关系,等以后工作中用到再翻翻就好了。
5. Tomcat使用线程池配置高并发连接
1:配置executor属性
打开/conf/server.xml文件,在Connector之前配置一个线程池:
重要参数说明:name :共享线程池的名字。这是Connector为了共享线程池要引用的名字,该名字必须唯一。默认值:None; namePrefix :在JVM上,每个运行线程都可以有一个name 字符串。这一属性为线程池中每个线程的name字符串设置了一个前缀,Tomcat将把线程号追加到这一前缀的后面。默认值:tomcat-exec-; maxThreads :该线程池可以容纳的最大线程数。默认值:200; maxIdleTime :在Tomcat关闭一个空闲线程之前,允许空闲线程持续的时间(以毫秒为单位)。只有当前活跃的线程数大于minSpareThread的值,才会关闭空闲线程。默认值:60000(一分钟)。 minSpareThreads :Tomcat应该始终打开的最小不活跃线程数。默认值:25。
2:配置Connector
重要参数说明:executor :表示使用该参数值对应的线程池; minProcessors :服务器启动时创建的处理请求的线程数; maxProcessors :最大可以创建的处理请求的线程数; acceptCount :指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。
一.Tomcat内存优化
Tomcat内存优化主要是对 tomcat 启动参数优化,我们可以在 tomcat 的启动脚本 catalina.sh 中设置JAVA_OPTS 参数。
1.JAVA_OPTS参数说明
现公司服务器内存一般都可以加到最大2G ,所以可以采取以下配置:
在cygwin=false前添加
配置完成后可重启Tomcat ,通过以下命令进行查看配置是否生效:
首先查看Tomcat 进程号:
result
我们可以看到Tomcat 进程号是27698 。
查看是否配置生效:
能在输出的信息中找到Heap Configuration中看到MaxHeapSize 等参数已经生效。
二.Tomcat并发优化
1.Tomcat连接相关参数
在Tomcat 配置文件 server.xml 中的 配置中
1.参数说明
minProcessors :最小空闲连接线程数,用于提高系统处理性能,默认值为 10 maxProcessors :最大连接线程数,即:并发处理的最大请求数,默认值为 75 acceptCount :允许的最大连接数,应大于等于 maxProcessors ,默认值为 100 enableLookups :是否反查域名,取值为: true 或 false 。为了提高处理能力,应设置为 false connectionTimeout :网络连接超时,单位:毫秒。设置为 0 表示永不超时,这样设置有隐患的。通常可设置为 30000 毫秒。其中和最大连接数相关的参数为maxProcessors 和 acceptCount 。如果要加大并发连接数,应同时加大这两个参数。web server允许的最大连接数还受制于操作系统的内核参数设置,通常 Windows 是 2000 个左右, Linux是 1000 个左右。
2.Tomcat中的配置示例
2.调整连接器connector的并发处理能力
1.参数说明
maxThreads :客户请求最大线程数 minSpareThreads :Tomcat初始化时创建的 socket 线程数 maxSpareThreads :Tomcat连接器的最大空闲 socket 线程数 enableLookups :若设为true, 则支持域名解析,可把 ip 地址解析为主机名 redirectPort :在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口 acceptAccount :监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads ) connectionTimeout :连接超时 minProcessors :服务器创建时的最小处理线程数 maxProcessors :服务器同时最大处理线程数 URIEncoding :URL统一编码
2.Tomcat中的配置示例
3.Tomcat缓存优化
1.参数说明
compression :打开压缩功能 compressionMinSize :启用压缩的输出内容大小,这里面默认为2KB compressableMimeType :压缩类型 connectionTimeout :定义建立客户连接超时的时间. 如果为 -1, 表示不限制建立客户连接的时间
2.Tomcat中的配置示例
4.参考配置
1.旧有的配置
参考网络对服务器做过如下配置,拿出来分享下:
后来发现在访问量达到3 百万多的时候出现性能瓶颈。
2.更改后的配置
6. 几种开源Java Web容器线程池的实现方法简介
其中Resin从V3.0后需要购买才能用于商业目的,而其他两种则是纯开源的。可以分别从他们的网站上下载最新的二进制包和源代码。
作为Web容器,需要承受较高的访问量,能够同时响应不同用户的请求,能够在恶劣环境下保持较高的稳定性和健壮性。在HTTP服务器领域,ApacheHTTPD的效率是最高的,也是最为稳定的,但它只能处理静态页面的请求,如果需要支持动态页面请求,则必须安装相应的插件,比如mod_perl可以处理Perl脚本,mod_python可以处理Python脚本。
上面介绍的三中Web容器,都是使用Java编写的HTTP服务器,当然他们都可以嵌到Apache中使用,也可以独立使用。分析它们处理客户请求的方法有助于了解Java多线程和线程池的实现方法,为设计强大的多线程服务器打好基础。
Tomcat是使用最广的Java Web容器,功能强大,可扩展性强。最新版本的Tomcat(5.5.17)为了提高响应速度和效率,使用了Apache Portable Runtime(APR)作为最底层,使用了APR中包含Socket、缓冲池等多种技术,性能也提高了。APR也是Apache HTTPD的最底层。可想而知,同属于ASF(Apache Software Foundation)中的成员,互补互用的情况还是很多的,虽然使用了不同的开发语言。
Tomcat 的线程池位于tomcat-util.jar文件中,包含了两种线程池方案。方案一:使用APR的Pool技术,使用了JNI;方案二:使用Java实现的ThreadPool。这里介绍的是第二种。如果想了解APR的Pool技术,可以查看APR的源代码。
ThreadPool默认创建了5个线程,保存在一个200维的线程数组中,创建时就启动了这些线程,当然在没有请求时,它们都处理等待状态(其实就是一个while循环,不停的等待notify)。如果有请求时,空闲线程会被唤醒执行用户的请求。
具体的请求过程是:服务启动时,创建一个一维线程数组(maxThread=200个),并创建空闲线程(minSpareThreads=5个)随时等待用户请求。当有用户请求时,调用 threadpool.runIt(ThreadPoolRunnable)方法,将一个需要执行的实例传给ThreadPool中。其中用户需要执行的实例必须实现ThreadPoolRunnable接口。 ThreadPool首先查找空闲的线程,如果有则用它运行要执行ThreadPoolRunnable;如果没有空闲线程并且没有超过 maxThreads,就一次性创建minSpareThreads个空闲线程;如果已经超过了maxThreads了,就等待空闲线程了。总之,要找到空闲的线程,以便用它执行实例。找到后,将该线程从线程数组中移走。接着唤醒已经找到的空闲线程,用它运行执行实例(ThreadPoolRunnable)。运行完ThreadPoolRunnable后,就将该线程重新放到线程数组中,作为空闲线程供后续使用。
由此可以看出,Tomcat的线程池实现是比较简单的,ThreadPool.java也只有840行代码。用一个一维数组保存空闲的线程,每次以一个较小步伐(5个)创建空闲线程并放到线程池中。使用时从数组中移走空闲的线程,用完后,再归还给线程池。
7. 怎样确定 Web 应用程序的线程池大小
在部署 web 应用到生产环境,或者在对 web 应用进行性能测试的时候,经常会有人问:如何决定 web 应用线程池大小?决定一个 IO 阻塞型 web 应用的线程池大小是一项很艰巨的任务。通常是通过进行大量的性能测试来完成。在一个 web 应用中同时拥有多个线程池会让决定最优线程池大小的过程变得更加复杂。本文将就这个常见的问题进行一些讨论和建议。
8. 需要创建一静态 线程池 每来一个web请求 作为一个线程,放入池中处理业务流程
ThreadPoolExecutor .excute(new Thread(){
public void run(){
// 请求处理
}
});