- 浏览: 239317 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
di1984HIT:
学习了。
CMS项目中用到的技术(全) -
di1984HIT:
就是用xml麻烦~
RESTEasy入门 -
di1984HIT:
学习了~~
RESTEasy入门 -
真三武侯:
写得很好,感谢分享经验心得!
RESTEasy入门 -
fangcensi:
是不是还有一个application文件,没写出来
RESTEasy入门
深入浅出多线程(4)对CachedThreadPool OutOfMemoryError问题的一些想法
- 博客分类:
- JESE
线程池是Conncurrent包提供给我们的一个重要的礼物。使得我们没有必要维护自个实现的心里很没底的线程池了。但如何充分利用好这些线程池来加快我们开发与测试效率呢?当然是知己知彼。本系列就说说对CachedThreadPool使用的一下问题。
下面是对CachedThreadPool的一个测试,程序有问题吗?
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CachedThreadPoolIssue {
/**
* @param args
*/
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for ( int i = 1 ; i < 8000 ; i ++ )
es.submit( new task());
}
}
class task implements Runnable{
@Override
public void run() {
try {
Thread.sleep( 4000 );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果对JVM没有特殊的设置,并在Window平台上,那么就会有一下异常的发生:
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.addIfUnderMaximumPoolSize(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
at net.blogjava.vincent.CachedThreadPoolIssue.main(CachedThreadPoolIssue.java:19)
看看Doc对该线程池的介绍:
Creates a thread pool that creates new threads as needed, but will
reuse previously constructed threads when they are available. These
pools will typically improve the performance of programs that execute
many short-lived asynchronous tasks. Calls to execute will reuse
previously constructed threads if available. If no existing thread is
available, a new thread will be created and added to the pool. Threads
that have not been used for sixty seconds are terminated and removed
from the cache. Thus, a pool that remains idle for long enough will not
consume any resources. Note that pools with similar properties but
different details (for example, timeout parameters) may be created
using ThreadPoolExecutor constructors.
有以下几点需要注意:
1. 指出会重用先前的线程,不错。
2. 提高了短Task的吞吐量。
3. 线程如果60s没有使用就会移除出Cache。
好像跟刚才的错误没有关系,其实就第一句话说了问题,它会按需要创建新的线程,上面的例子一下提交8000个Task,意味着该线程池就会创建8000线程,当然,这远远高于JVM限制了。
注:在JDK1.5中,默认每个线程使用1M内存,8000M !!! 可能吗!!
所以我感觉这应该是我遇到的第一个Concurrent不足之处,既然这么设计,那么就应该在中Doc指出,应该在使用避免大量Task提交到给CachedThreadPool.
可能读者不相信,那么下面的例子说明了他创建的Thread。
在ThreadPoolExecutor提供的API中,看到它提供beforeExecute
和afterExecute两个可以在子类中重载的方法,该方法在线程池中线程执行Task之前与之后调用。所以我们在beforeExexute中查看
目前线程编号就可以确定目前的线程数目.
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CachedThreadPoolIssue {
/**
* @param args
*/
public static void main(String[] args) {
ExecutorService es = new LogThreadPoolExecutor( 0 , Integer.MAX_VALUE,
60L , TimeUnit.SECONDS,
new SynchronousQueue < Runnable > ());
for ( int i = 1 ; i < 8000 ; i ++ )
es.submit( new task());
}
}
class task implements Runnable{
@Override
public void run() {
try {
Thread.sleep( 600000 );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class LogThreadPoolExecutor extends ThreadPoolExecutor{
public LogThreadPoolExecutor( int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue < Runnable > workQueue) {
super (corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
protected void beforeExecute(Thread t, Runnable r) {
System.out.println(t.getName());
}
protected void afterExecute(Runnable r, Throwable t) {
}
}
测试结果如图:
当线程数达到5592是,只有在任务管理器Kill该进程了。
如何解决该问题呢,其实在刚才实例化时就看出来了,只需将
new LogThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
Integer.MAX_VALUE 改为合适的大小。对于该参数的含义,涉及到线程池的实现,将会在下个系列中指出。
当然,其他的解决方案就是控制Task的提交速率,避免超过其最大限制。
发表评论
-
Java基本功——Reference
2011-10-08 17:52 1078版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声 ... -
Caused by: org.codehaus.jackson.map.JsonMappingException
2011-08-29 16:09 12329写道 No serializer found for cla ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat(2)
2011-08-10 13:44 3802如果能熟练运用这些命令,尤其是在linux下,那么完全可以代替 ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat (1)
2011-08-10 13:44 1140jstack -- 如果java程序崩溃生成core文 ... -
IT公司中最流行的10种编程语言
2011-08-05 13:12 9431. C语言 C语言是一种 ... -
JDK自带线程池总类介绍介绍
2011-07-28 20:38 6951、newFixedThreadPool创建一个指定工作线程数 ... -
Java多线程--让主线程等待所有子线程执行完毕
2011-07-28 19:25 3311数据量很大百万条记录,因此考虑到要用多线程并发执行,在写 ... -
Quartz管理类
2011-07-18 17:11 1161package com.sihuatech.project.t ... -
JAVA写文件到FTP的几种方法
2011-07-18 11:32 25911.使用URL: URL url = n ... -
为什么会出现 java.util.ConcurrentModificationException 异常?
2011-07-15 14:47 1456工作中碰到个ConcurrentModificationExc ... -
装饰模式
2011-07-12 11:41 12061) 装饰模式 装饰模式 (Decor ... -
全面解析Java中的String对象的数据类型
2011-07-11 12:56 9671. 首先String不属于8种基本数据类型,String是一 ... -
oscache配置详解
2011-07-08 14:36 2068#一、内存缓存或硬盘、数据库缓存 cache.memory= ... -
oscache使用指南
2011-07-07 15:19 2428一、简介 Cache是一种用于提高系统响应速度、改善 ... -
java文件操作
2011-07-05 12:10 700package Test; import ja ... -
map的三种遍历方法!
2011-07-04 13:27 921集合的一个很重要的操作---遍历,学习了三种遍历方法,三种 ... -
Java中String类型的参数传递问题的解析
2011-06-29 18:31 1148publicclass StringAsParamOfMeth ... -
not in 优化
2011-06-20 14:35 145601.select * from emp where emp_ ... -
简单工厂模式与策略模式的区别
2011-06-14 16:10 3247工厂(Factory)模式我们可以做如下理解,假设有一个A ... -
UML中的关系
2011-05-30 17:14 879uml定义的关系主要有六种:依赖、类属、关联、实现、聚合和组合 ...
相关推荐
Android多线程、AsyncTask、Thread、FixedThreadPool、CachedThreadPool、SingleThreadExecutor、runOnUIThread使用
可调用线程被创建,每个线程包含一个 POST 请求的数据并采用一个关键字作为参数。 为了确保可扩展性,我们定义了一次允许的最大线程数。 如果可调用线程返回成功 HTTP 响应的字符串值,我们会增加线程数量,因为...
其中使用2,3,4来创建线程池时,其内部也是通过ThreadPoolExecutor来生成线程池的。我们来分析下ThreadPoolExecutor的构造参数以及内部实现。 构造参数 ThreadPoolExecutor完整的构造方法如下(其
3.2 CachedThreadPool 3.3 ScheduledThreadPool 3.4 SingleThreadExecutor 3.5 WorkStealingPool 线程池的参数配置 4.1 核心线程数 4.2 最大线程数 4.3 线程空闲时间 4.4 阻塞队列 4.5 线程工厂 4.6 拒绝策略 线程池...
阿里巴巴开发手册中编程规约-并发处理中提到: 【强制】线程池不允许使用Executors去创建... 2) CachedThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。 我们来用程序验证下
该文档详细记录了Executor框架结构、使用示意图、ThreadPoolExecutor使用示例、线程池原理分析、几种常见线程池(FixedThreadPool、SingleThreadExecutor、CachedThreadPool)的详解以及线程池大小确定等内容
主要给大家介绍了关于Java中四种线程池的使用方法,四种线程池分别包括FixedThreadPool、CachedThreadPool、ScheduledThreadPool以及SingleThreadExecutor,文中给出了详细的示例代码供大家参考,需要的朋友们下面来...