c指出,应该在使用避免大量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) {
}
}
深入浅出多线程(4)对CachedThreadPool OutOfMemoryError问题的一些想法(3)
时间:2011-09-07 BlogJava vincent
测试结果如图:
当线程数达到5592是,只有在任务管理器Kill该进程了。
如何解决该问题呢,其实在刚才实例化时就看出来了,只需将
new LogThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
Integer.MAX_VALUE 改为合适的大小。对于该参数的含义,涉及到线程池的 实现,将会在下个系列中指出。
当然,其他的解决方案就是控制Task的提交速率,避免超过其最大限制。 |