Спорадические проблемы при запуске многопоточного проекта Java в Win7

Я работаю над проектом, который требует много памяти и вычислений. Значительная часть выполнения использует многопоточность с помощью FixedThreadPool. Короче говоря, у меня есть 1 поток для получения данных из нескольких удаленных мест (используя URL-соединения) и заполнения BlockingQueue объектами для анализа и n потоков, которые выбирают эти объекты и выполняют анализ. edit: see code below

Теперь эта установка работает как шарм на моей Linux машине под управлением OpenSUSE 11.3, но коллега, тестирующий ее на очень похожей машине под управлением Win7, получает пользовательские уведомления о таймаутах при опросе очереди (см. код ниже), на самом деле их много. Я пытался проследить за использованием процессора на ее машине, и оказалось, что программа использует не более 15% процессора, в то время как на моей машине использование процессора зашкаливает, как я и предполагал.

Мой вопрос заключается в том, может ли это быть признаком "голодания" очереди? Может ли быть так, что поток-производитель не получает достаточно времени на процессоре? Если да, то как мне сделать так, чтобы дать одному конкретному потоку в пуле более высокий приоритет?

UPDATE:. Я пытался определить проблему, но безрезультатно... Однако я получил некоторые новые знания.

  • Профилирование выполнения кода с помощью JVisualVM демонстрирует очень необычное поведение. Методы вызываются короткими всплесками процессорного времени с несколькими секундами отсутствия прогресса между ними. Для меня это означает, что ОС каким-то образом тормозит процесс.

  • Отключение антивируса и демонов резервного копирования не оказывает существенного влияния на ситуацию

  • Изменение приоритета java.exe (единственного экземпляра) через диспетчер задач (по совету здесь) также ничего не меняет. (Учитывая это, я не мог дать приоритет "реального времени" java, и мне пришлось довольствоваться "высоким" приоритетом)

  • Профилирование использования сети показывает хороший поток данных внутри и снаружи, поэтому я предполагаю, что это не узкое место (хотя это составляет значительную часть времени выполнения процесса, но это я уже знаю, и это практически тот же процент, что и на моей Linux машине).

Есть идеи, как ОС Win7 может ограничивать время работы процессора в моем проекте? если дело не в ОС, то что может быть ограничивающим фактором? Я хотел бы еще раз подчеркнуть, что машина НЕ работает одновременно с другими интенсивными вычислениями, и нет почти никакой нагрузки на процессор, кроме моего программного обеспечения. Это сводит меня с ума...

EDIT: соответствующий код

public ConcurrencyService(Dataset d, QueryService qserv, Set 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.

12
задан Mat 17 May 2012 в 21:00
поделиться