我正在做一个内存和计算密集型的项目。执行的很大一部分是利用FixedThreadPool的多线程。简而言之,我有一个线程,用于从多个远程位置(使用URL连接)获取数据,并使用要分析的对象填充BlockingQueue,以及选择这些对象并运行分析的n个线程。编辑:参见下面的代码
现在,这个设置在运行OpenSUSE 11.3的Linux机器上很有魅力,但是一位同事正在一台非常相似的机器上测试它,运行Win7的是在队列轮询中获得自定义的超时通知(参见下面的代码),实际上很多都是这样。我一直在试图监视她的机器上的处理器使用情况,似乎软件没有得到超过15%的CPU,而在我的机器上,处理器的使用达到了我的预期。
我的问题是,这是否“饥饿”的迹象?会不会是因为生产者线程没有足够的cpu时间?如果是这样的话,我如何为池中的一个特定线程赋予更高的优先级?
更新:我一直在努力找出问题,没有joy.然而,我确实获得了一些新的见解。
对于Win7操作系统如何将cpu时间限制在我的项目上,有什么想法吗?如果不是操作系统,限制因素是什么?我想再次强调的是,这台机器不同时运行任何其他的计算密集型,除了我的软件之外,cpus上几乎没有负载。这快把我逼疯了。
编辑:相关代码
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);
}
}类QueryingAction是一个简单的Runnable,它在指定的QueryService对象中调用数据采集方法,然后填充BlockingQueue。AnalysisAction类为MyObject的单个实例执行所有的数字处理。
发布于 2012-02-02 18:10:56
因此,经过数周的篡改,在代码和其他类型的痛苦中挣扎,我想我有一个突破,“片刻的清晰”,如果你愿意的话.
我设法证明了这个程序可以在我的Linux机器上表现出同样的缓慢行为,并且确实可以在有问题的Win-7机器上运行完全节流阀。问题的症结似乎是系统/缓存文件的某种损坏,这些文件用于存储以前查询的结果,并且总体上加快了分析的速度。你会喜欢讽刺的,在这种情况下,他们似乎是极慢分析的原因。回想起来,我应该知道(拉奥卡姆剃刀).
我仍然不知道腐败是如何发生的,但至少它可能与不同的操作系统无关。然而,使用我机器上的系统文件只会使Win7主机上的输出增加约40%。对进程进行更多的分析还发现,奇怪的是,在Win7上有更多的GC活动,这显然花费了大量的CPU时间来处理数字。让-Xmx2g处理过多的垃圾收集,进程的CPU使用率高达95%-96%,线程运行平稳。
现在我已经回答了我最初的问题,我不得不说,在Linux环境下,总体java响应性肯定更好,即使没有分配更多堆内存,在后台运行广泛分析时,我也可以轻松地执行多任务。在Win-7,e.x中,事情并不顺利。一旦分析以全速进行,调整GUI的大小是非常缓慢的。
感谢所有的答复,我很抱歉对部分误导性问题的描述。我只是分享了我在尽我最大能力进行调试时发现的情况。不管怎样,我相信赏金是交给彼得·劳瑞的,因为他很早就指出了一个I/O问题,是他关于伐木线的建议最终使我找到了答案。
发布于 2011-12-19 11:03:55
我怀疑生产者线程获取/加载源数据的速度不够快。这可能不是缺少CPU,而是与IO相关的问题。(不知道为什么BlockingQueue上有超时时间)
可能值得有一个线程定期记录添加的任务数和队列长度(例如每5-15秒)。
发布于 2012-02-01 15:22:02
因此,如果我正确理解了您的问题,您将有一个线程来获取数据,多个线程来分析所获取的数据。您的问题是线程没有正确地同步以一起运行并充分利用处理器。
你有一个尖锐的生产者-消费者的单一生产者和几个消费者问题。我建议您稍加修改代码,使之有几个独立的使用者线程,这些线程总是等待资源可用,然后才能运行。这样可以保证最大限度地使用处理器。
消费者线索:
while (!terminate)
{
synchronized (Producer.getLockObject())
{
try
{
//sleep (no processing at all)
Producer.getLockObject().wait();
}
catch (Exceptions..)
}
MyObject p = Producer.getObjectFromQueue(); //this function should be synchronized
//Analyse fetched data, and submit it to somewhere...
} 出厂线:
while (!terminate)
{
MyObject newData = fetchData(); //fetch data from remote location
addDataToQueueu(newData); //this should also be synchronized
synchronized (getLockObject())
{
//wake up one thread to deal with the data
getLockObject().notify();
}
}您可以看到,这样,您的线程总是在执行有用的工作或休眠。这只是用来举例说明的草案代码。请参阅这里的更多解释:to.shtml和http://www.java-samples.com/showtutorial.php?tutorialid=306
https://stackoverflow.com/questions/8560319
复制相似问题