【发布时间】:2011-07-27 08:04:32
【问题描述】:
我正在对现有 Java 应用程序进行增强。该应用程序是一个消息处理器,每天处理数百万条消息。它基本上是使用 Core Java 编写的,线程和队列是使用 Collection 类实现的。
在此应用程序中,某些类型的消息在单个线程中运行。我的任务是使应用程序的这个特定部分成为多线程以更快地处理消息,因为我们有双处理器。
由于我们使用的是 Java 5,所以我采取了使用 ThreadPoolExcecutor 的方法。我为每个客户端创建了处理器线程,以便可以在其自己的线程中处理特定线程的消息。处理器线程正在实现 Callable 接口,因为这将允许我检查未来对象是否已完成前一个任务。
在初始化过程中,我将检查所有客户端并为每个客户端创建处理器线程,并使用它们的 id 作为唯一键将其存储在 map 中。为了跟踪之前提交的作业,我确实使用相同的 id 作为唯一键再次将未来对象保留在另一个地图中。
以下是我使用的一些 sn-p 代码:在主类中 -
ThreadPoolExecutor threadPool = null;
int poolSize = 20;
int maxPoolSize = 50;
long keepAliveTime = 10;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(1000);
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize,keepAliveTime, TimeUnit.SECONDS, queue);
....
....
for (each client...) {
id = getId()..
future = futuremap.get(id);
if(!future.isDone())
continue;
if(future == null || future.isDone()) {
processor = processormap.get(id);
if(processor == null) {
processor = new Processor(.....);
//add to the map
processormap.put(id,processor);
}
//submit the processor
future = threadPool.submit(processor );
futuremap.put(id,future);
}
}
处理器线程
public class MyProcessor implements Callable<String> {
.....
.....
public String call() {
....
....
}
}
问题
上述实现在我的测试环境中运行良好。但是,在生产环境中(Edit#1 - Ubuntu、Linux Slackware、Java - 1.6.0_18),我们观察到应用程序的其他线程不是通过这个管理的新的 ThreadpoolExecutor 受到影响。即,他们的任务被延迟了几个小时。是因为 ThreadPoolExecutors 创建的线程正在占用全部资源或其他任何资源,而没有给其他线程机会。
使用 ThreadPoolExceutor 创建的新线程正在执行独立的任务,并且不会与其他线程争用资源。即,没有竞争条件场景。
在日志中,对于新的线程,我可以看到最多有 20 个线程在运行(corepoolsize)并且没有拒绝异常,即提交的数量在队列的范围内。
任何想法为什么会发生这种情况?
提前致谢。
【问题讨论】:
-
您是否在应用程序的任何位置更改线程优先级(来自池或其他)?这在不同的平台上可能会产生不同的效果。
-
没有。没有为线程明确设置优先级。
-
我正在使用 Java 1.6.0_18(64 位服务器 VM(内部版本 16.0-b13,混合模式)。服务器操作系统 - Linux - 2.6.27.9。
-
ThreadPool 线程是否受计算约束? IE。它们是否处于没有外部交互且运行很长时间的紧密循环中?如果是这种情况,您可能需要偶尔致电
Thread#yield()。 -
处理器线程基本上连接到数据库并将消息发送给客户端。这些过程本身不需要更长的时间。问题在于较旧的线程,如果没有我的实现,它们的工作速度非常快。在我为应用程序的一部分实现 ThreadPoolExecutor 之后,其他线程正在延迟。
标签: java threadpool executors