在Win7中运行多线程Java项目的零星问题

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是一个简单RunnableQueryService函数,它在指定的对象中调用数据获取方法,然后填充a BlockingQueue.本AnalysisAction类对于单个实例的所有数字运算MyObject.

pos*_*def 1

因此,经过几周的摆弄、代码摔跤和其他类型的痛苦之后,我想我已经取得了突破,“一个清晰的时刻”,如果你愿意的话……

我设法证明该程序可以在我的 Linux 计算机上表现出相同的缓慢行为,并且确实可以在有问题的 Win-7 计算机上全力运行。问题的症结似乎是用于存储先前查询结果的系统/缓存文件的某种损坏,总体而言,加快了分析速度。你一定会喜欢这种讽刺,在这种情况下,它们似乎是分析极其缓慢的原因。回想起来,我应该知道(奥卡姆剃刀)......

我仍然不确定损坏是如何发生的,但至少它可能与不同的操作系统无关。然而,使用我的机器上的系统文件只能将 Win7 主机上的输出增加最多 40% 左右。对进程进行更多分析还发现,奇怪的是,Win7 上的 GC 活动明显更多,这显然占用了大量的 CPU 时间用于数字处理。Giving-Xmx2g解决了过多的垃圾收集问题,进程的 CPU 使用率飙升至 95-96%,线程运行平稳。

既然我原来的问题得到了解答,我不得不说,在 Linux 环境下,整体 Java 响应能力肯定更好,即使没有分配更多堆内存,我也可以在后台运行大量分析时轻松执行多任务。在 Win-7 中事情并不那么顺利,一旦全速分析开始,调整 GUI 大小的速度就会非常慢。

感谢您的所有回复,对于部分误导性的问题描述,我深表歉意。我只是分享了我在尽力调试时发现的内容。无论如何,我相信 Peter Lawrey 会得到赏金,因为他很早就指出了 I/O 问题,正是他关于记录器线程的建议最终让我找到了答案。