pos*_*def 12 java multithreading threadpool thread-priority
我正在开发一个内存和计算密集型项目.执行的很大一部分利用a的多线程FixedThreadPool.简而言之; 我有一个线程用于从几个远程位置(使用URL连接)获取数据并填充BlockingQueue要分析的对象和n个挑选这些对象并运行分析的线程.编辑:见下面的代码
现在,这种设置就像运行的OpenSUSE 11.3我的Linux机器上的魅力,但一个同事正在测试其运行Win7的是得到一个非常类似的机器上的自定义通知队列轮询超时(见下面的代码),他们很多实际.我一直在尝试监控她的机器上的处理器使用情况,看起来该软件在我的机器上没有超过15%的CPU,处理器的使用量达到了我的预期.
那么,我的问题是,这可能是队列"饥饿"的标志吗?可能是因为生产者线程没有获得足够的CPU时间?如果是这样,我如何才能更优先考虑池中的一个特定线程?
更新: 我一直试图找出问题,没有任何快乐......但我确实获得了一些新的见解.
使用JVisualVM分析代码的执行表明了一种非常奇特的行为.这些方法在短时间的CPU时间内被调用,两次之间没有任何进展.这对我来说意味着操作系统在某种程度上对这个过程起了制动作用.
禁用防病毒和备份守护进程对此问题没有任何重大影响
通过任务管理器(这里建议)更改java.exe(唯一实例)的优先级也不会改变任何内容.(话虽这么说,我不能给java"实时"优先级,并且必须满足于"高"prio)
分析网络使用情况显示出良好的数据流入和流出,因此我猜这不是瓶颈(虽然它是流程执行时间的相当一部分,但我已经知道并且几乎与我在Linux机器上得到的东西).
关于Win7操作系统如何限制我的项目的CPU时间的任何想法?如果它不是操作系统,可能是什么限制因素?我想再次强调,机器不会同时运行任何其他计算密集,除了我的软件之外,cpu几乎没有任何负载.这真让我抓狂...
编辑:相关代码
public ConcurrencyService(Dataset d, QueryService qserv, Set<MyObject> s){
timeout = 3;
this.qs = qserv;
this.bq = qs.getQueue();
this.ds = d;
this.analyzedObjects = s;
this.drc = DebugRoutineContainer.getInstance();
this.started = false;
int nbrOfProcs = Runtime.getRuntime().availableProcessors();
poolSize = nbrOfProcs;
pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(poolSize);
drc.setScoreLogStream(new PrintStream(qs.getScoreLogFile()));
}
public void serve() throws InterruptedException {
try {
this.ds.initDataset();
this.started = true;
pool.execute(new QueryingAction(qs));
for(;;){
MyObject p = bq.poll(timeout, TimeUnit.MINUTES);
if(p != null){
if (p.getId().equals("0"))
break;
pool.submit(new AnalysisAction(ds, p, analyzedObjects, qs.getKnownAssocs()));
}else
drc.log("Timed out while waiting for an object...");
}
} catch (Exception ex) {
ex.printStackTrace();
String exit_msg = "Unexpected error in core analysis, terminating execution!";
}finally{
drc.log("--DEBUG: Termination criteria found, shutdown initiated..");
drc.getMemoryInfo(true); // dump meminfo to log
pool.shutdown();
int mins = 2;
int nCores = poolSize;
long totalTasks = pool.getTaskCount(),
compTasks = pool.getCompletedTaskCount(),
tasksRemaining = totalTasks - compTasks,
timeout = mins * tasksRemaining / nCores;
drc.log("--DEBUG: Shutdown commenced, thread pool will terminate once all objects are processed, " +
"or will timeout in : " + timeout + " minutes... \n" + compTasks + " of " + (totalTasks -1) +
" objects have been analyzed so far, " + "mean process time is: " +
drc.getMeanProcTimeAsString() + " milliseconds.");
pool.awaitTermination(timeout, TimeUnit.MINUTES);
}
}
Run Code Online (Sandbox Code Playgroud)
该类QueryingAction是一个简单Runnable的QueryService函数,它在指定的对象中调用数据获取方法,然后填充a BlockingQueue.本AnalysisAction类对于单个实例的所有数字运算MyObject.
因此,经过几周的摆弄、代码摔跤和其他类型的痛苦之后,我想我已经取得了突破,“一个清晰的时刻”,如果你愿意的话……
我设法证明该程序可以在我的 Linux 计算机上表现出相同的缓慢行为,并且确实可以在有问题的 Win-7 计算机上全力运行。问题的症结似乎是用于存储先前查询结果的系统/缓存文件的某种损坏,总体而言,加快了分析速度。你一定会喜欢这种讽刺,在这种情况下,它们似乎是分析极其缓慢的原因。回想起来,我应该知道(奥卡姆剃刀)......
我仍然不确定损坏是如何发生的,但至少它可能与不同的操作系统无关。然而,使用我的机器上的系统文件只能将 Win7 主机上的输出增加最多 40% 左右。对进程进行更多分析还发现,奇怪的是,Win7 上的 GC 活动明显更多,这显然占用了大量的 CPU 时间用于数字处理。Giving-Xmx2g解决了过多的垃圾收集问题,进程的 CPU 使用率飙升至 95-96%,线程运行平稳。
既然我原来的问题得到了解答,我不得不说,在 Linux 环境下,整体 Java 响应能力肯定更好,即使没有分配更多堆内存,我也可以在后台运行大量分析时轻松执行多任务。在 Win-7 中事情并不那么顺利,一旦全速分析开始,调整 GUI 大小的速度就会非常慢。
感谢您的所有回复,对于部分误导性的问题描述,我深表歉意。我只是分享了我在尽力调试时发现的内容。无论如何,我相信 Peter Lawrey 会得到赏金,因为他很早就指出了 I/O 问题,正是他关于记录器线程的建议最终让我找到了答案。