在Win7中运行多线程Java项目时出现的零星问题
我正在做一个既需要内存又需要计算的项目。执行的很大一部分通过在Win7中运行多线程Java项目时出现的零星问题,java,multithreading,threadpool,thread-priority,Java,Multithreading,Threadpool,Thread Priority,我正在做一个既需要内存又需要计算的项目。执行的很大一部分通过FixedThreadPool利用多线程。简言之我有1个线程用于从多个远程位置获取数据(使用URL连接),并用要分析的对象填充阻塞队列,还有n个线程用于拾取这些对象并运行分析编辑:参见下面的代码 现在,这个设置在我运行OpenSUSE 11.3的Linux机器上非常有用,但是一位同事正在运行Win7的非常类似的机器上测试它,在队列轮询中得到了超时的自定义通知(请参见下面的代码),实际上有很多。我一直在尝试监控她机器上的处理器使用情况,但
FixedThreadPool
利用多线程。简言之我有1个线程用于从多个远程位置获取数据(使用URL连接),并用要分析的对象填充阻塞队列
,还有n个线程用于拾取这些对象并运行分析编辑:参见下面的代码
现在,这个设置在我运行OpenSUSE 11.3的Linux机器上非常有用,但是一位同事正在运行Win7的非常类似的机器上测试它,在队列轮询中得到了超时的自定义通知(请参见下面的代码),实际上有很多。我一直在尝试监控她机器上的处理器使用情况,但软件似乎无法获得超过15%的CPU,而在我的机器上,处理器使用率达到了顶峰,正如我所预期的那样
那么,我的问题是,这是否是排队“挨饿”的迹象?是不是生产者线程没有得到足够的cpu时间?如果是这样的话,我如何给池中的一个特定线程更高的优先级
更新:
我一直在努力找出问题所在,但毫无乐趣。。。然而,我确实获得了一些新的见解
- 使用JVisualVM评测代码的执行过程演示了一种非常奇特的行为。这些方法在短时间的CPU时间内被调用,其间几秒钟没有任何进展。对我来说,这意味着操作系统不知何故在这个过程中踩下了刹车
- 禁用反病毒和备份守护进程不会对该问题产生任何重大影响
- 通过任务管理器(adviced)更改java.exe(唯一实例)的优先级也不会更改任何内容。(尽管如此,我不能给java“实时”优先级,只能满足于“高”优先级)
- 分析网络使用情况显示出良好的数据流入和流出,因此我猜测这不是瓶颈(虽然这是进程执行时间的一个相当大的部分,但我已经知道,并且与我在Linux机器上得到的数据百分比几乎相同)
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);
}
}
公共并发服务(数据集d、查询服务qserv、集合s){
超时=3;
this.qs=qserv;
this.bq=qs.getQueue();
这是d.ds=d;
此.analyzedObjects=s;
this.drc=DebugRoutineContainer.getInstance();
this.start=false;
int nbrofpocs=Runtime.getRuntime().availableProcessors();
poolSize=nbroc;
池=(ThreadPoolExecutor)执行器。newFixedThreadPool(池大小);
setScoreLogStream(新的PrintStream(qs.getScoreLogFile());
}
public void service()抛出InterruptedException{
试一试{
这是.ds.initDataset();
this.started=true;
执行(新查询操作(qs));
对于(;;){
MyObject p=bq.poll(超时,时间单位:分钟);
如果(p!=null){
if(p.getId().equals(“0”))
打破
提交(新的AnalysisAction(ds、p、AnalysizedObjects、qs.getKnownAssocs());
}否则
log(“等待对象时超时…”);
}
}捕获(例外情况除外){
例如printStackTrace();
String exit_msg=“核心分析中出现意外错误,正在终止执行!”;
}最后{
log(“--DEBUG:找到终止条件,已启动关机…”);
drc.getMemoryInfo(true);//将meminfo转储到日志
pool.shutdown();
整数分钟=2;
int nCores=池大小;
long totalTasks=pool.getTaskCount(),
compTasks=pool.getCompletedTaskCount(),
tasksRemaining=totalTasks-compTasks,
超时=分钟*任务维护/nCores;
log(“--DEBUG:Shutdown已开始,线程池将在处理完所有对象后终止,”+
或将在“+(totalTasks-1)”中的“+timeout+”分钟内超时…\n“+compTasks+”
到目前为止已分析对象,“+”平均处理时间为:+
getMeanProcTimeAsString()+“毫秒”);
池。等待终止(超时,时间单位。分钟);
}
}
类
queryaction
是一个简单的Runnable
,它在指定的QueryService
对象中调用数据采集方法,然后填充阻塞队列
。AnalysisAction
类对MyObject
的单个实例执行所有的数字运算 我怀疑生产者线程获取/加载源数据的速度不够快。这可能不是CPU不足,而是与IO相关的问题。(不确定您的封锁队列为何超时)
让一个线程定期记录添加的任务数量和队列长度(例如,每5-15秒一次)这样的事情可能是值得的。优先级没有帮助,因为问题不是决定谁获得宝贵资源的问题——资源利用率没有最大化。生产者线程得不到足够CPU时间的唯一方法是,它没有准备好运行。优先权没有帮助,因为问题不是问题 这台机器有多少芯?生产者线程可能正在全速运行,但仍然没有足够的CPU来运行。它也是
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();
}
}