- 浏览: 243072 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
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 1128版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声 ... -
Caused by: org.codehaus.jackson.map.JsonMappingException
2011-08-29 16:09 12370写道 No serializer found for cla ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat(2)
2011-08-10 13:44 3868如果能熟练运用这些命令,尤其是在linux下,那么完全可以代替 ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat (1)
2011-08-10 13:44 1188jstack -- 如果java程序崩溃生成core文 ... -
IT公司中最流行的10种编程语言
2011-08-05 13:12 9921. C语言 C语言是一种 ... -
JDK自带线程池总类介绍介绍
2011-07-28 20:38 7481、newFixedThreadPool创建一个指定工作线程数 ... -
Java多线程--让主线程等待所有子线程执行完毕
2011-07-28 19:25 3361数据量很大百万条记录,因此考虑到要用多线程并发执行,在写 ... -
Quartz管理类
2011-07-18 17:11 1216package com.sihuatech.project.t ... -
JAVA写文件到FTP的几种方法
2011-07-18 11:32 26511.使用URL: URL url = n ... -
为什么会出现 java.util.ConcurrentModificationException 异常?
2011-07-15 14:47 1500工作中碰到个ConcurrentModificationExc ... -
装饰模式
2011-07-12 11:41 12491) 装饰模式 装饰模式 (Decor ... -
全面解析Java中的String对象的数据类型
2011-07-11 12:56 10241. 首先String不属于8种基本数据类型,String是一 ... -
oscache配置详解
2011-07-08 14:36 2134#一、内存缓存或硬盘、数据库缓存 cache.memory= ... -
oscache使用指南
2011-07-07 15:19 2480一、简介 Cache是一种用于提高系统响应速度、改善 ... -
java文件操作
2011-07-05 12:10 744package Test; import ja ... -
map的三种遍历方法!
2011-07-04 13:27 986集合的一个很重要的操作---遍历,学习了三种遍历方法,三种 ... -
Java中String类型的参数传递问题的解析
2011-06-29 18:31 1207publicclass StringAsParamOfMeth ... -
not in 优化
2011-06-20 14:35 150801.select * from emp where emp_ ... -
简单工厂模式与策略模式的区别
2011-06-14 16:10 3319工厂(Factory)模式我们可以做如下理解,假设有一个A ... -
UML中的关系
2011-05-30 17:14 925uml定义的关系主要有六种:依赖、类属、关联、实现、聚合和组合 ...
相关推荐
在IT行业中,多线程技术是一项重要的编程技巧,特别是在处理并发任务时,它能显著提升程序的执行效率。本示例“多线程发邮件”就是利用了这一特性,通过并发执行多个邮件发送任务,来加快邮件的发送速度。下面我们将...
Java通过`Thread`类和`Runnable`接口提供了对多线程的支持。创建线程有两种方式:继承`Thread`类或实现`Runnable`接口。后者更常用,因为它可以避免单继承的限制,并且线程与业务逻辑解耦。 多线程设计模式包括但不...
在Java中,Java并发工具包(JUC,Java Concurrency Utilities)是处理多线程问题的核心组件,提供了丰富的类和接口,如`Thread`、`ExecutorService`、`Semaphore`、`CountDownLatch`、`CyclicBarrier`等,这些工具...
以下是对Java多线程面试题59题集合中可能涉及的一些关键知识点的详细解析。 1. **线程的创建方式** - 继承Thread类:创建一个新的类,该类继承自Thread类,并重写其run()方法。 - 实现Runnable接口:创建一个实现...
Java提供了一些线程安全的集合类,如Vector、ConcurrentHashMap、CopyOnWriteArrayList等,它们内部已经实现了线程同步,可以避免在多线程环境下出现数据一致性问题。 通过以上内容,初学者可以对Java多线程有一个...
在安卓开发中,多线程技术是至关重要的,它能够帮助...综上所述,"火山安卓多线程技术源码"可能包含了以上各种技术的实现,通过研究这些源码,开发者可以深入理解Android平台上的多线程编程,提高应用性能和用户体验。
本文将详细讲解Android中的多线程,包括AsyncTask、Thread、ExecutorService(FixedThreadPool、CachedThreadPool、SingleThreadExecutor)以及如何在主线程中安全地更新UI。 首先,Android应用的主线程,也被称为...
Java多线程编程是Java开发中的...在"Java多线程编程核心技术_完整版.pdf"这本书中,可能涵盖了上述所有内容,深入探讨了Java多线程编程的各个方面,包括理论、实践案例和最佳实践,帮助开发者熟练掌握这一重要技术。
在深入探讨Java多线程与并发库的高级应用之前,我们首先需要回顾一下Java多线程的基础概念和技术要点。 ##### 1.1 线程的概念 在计算机科学中,线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是...
此外,死锁是多线程编程中常见的问题,当两个或更多的线程互相等待对方释放资源时就会发生。避免死锁的关键在于遵循死锁预防的四个条件:互斥、请求与保持、不剥夺和循环等待。Java提供了一些工具如jstack和VisualVM...
通过深入学习和实践这些Java多线程设计模式,开发者可以更好地理解和掌握多线程环境下的编程技巧,提高程序的并发性能和稳定性。在实际开发中,应根据具体需求选择合适的设计模式和并发工具,确保代码的正确性和高效...
Java 多线程(Synchronized+Volatile+JUC 并发工具原理+线程状态+CAS+线程池) Java 多线程是 Java 语言中的一...但是,多线程编程也存在一些挑战,如线程安全、死锁、饥饿等问题,因此需要小心设计和实施多线程程序。
本篇文章将深入探讨Java中的多线程编程,包括基本概念、实现方式以及常见问题和解决方案。 一、多线程基础 1.1 线程与进程 线程是操作系统分配CPU时间的基本单位,而进程则是一个独立的执行实体,拥有自己的内存...
Java多线程开发是Java开发中的重要组成部分,尤其在高并发场景下,合理地使用多线程技术可以显著提升程序的执行效率。然而,多线程编程也伴随着一系列挑战,如资源管理、线程安全、任务调度等。以下是对标题和描述中...
4. **简单多线程模型** 虽然可以并行处理多个连接,但随着连接数增加,创建和销毁线程的开销也会增大,可能造成服务器性能下降。 5. **线程池模型** 线程池提供了一种线程复用机制,固定数量的线程等待任务,如...
Java多线程是Java编程中的核心概念,尤其在面试中,它...通过解答这些题目,开发者能深入理解Java多线程的原理,并具备解决实际问题的能力。对于准备Java面试或提升编程能力的人员来说,这68道题无疑是极好的学习材料。
通过以上内容的学习,读者可以深入了解Java线程的高级使用方法,掌握如何在Java程序中高效地管理和控制线程,以及如何解决多线程环境下常见的问题。这对于开发高性能、高可用性的Java应用至关重要。
总之,理解和掌握多线程与线程池技术是Java程序员必备的技能,这不仅对面试有帮助,更是提升实际项目性能的关键。通过深入学习这些技术,可以更好地应对高并发环境下的挑战,为软件开发带来更高的效率和可靠性。
4. **线程安全**:线程安全意味着在多线程环境下,一段代码的执行不会导致数据不一致或异常。例如,Vector类是线程安全的,因为它使用了同步方法,而ArrayList则不是。 5. **线程池**:线程池是一种预先创建的线程...
为了解决这些问题,我们需要对线程进行控制和管理,这就需要使用线程池。 线程池顾名思义,就是放线程的大池子。它可以帮助我们管理线程,避免线程不可控和内存泄漏的问题。Android中有多种类型的线程池,如...