2013-10-10 3 views
0

Я создал программу, которая использует один поток для чтения данных из файла в связанный список, позволяет называть его LL1. Из этого я создал пул потоков, который распределяет каждый поток с задачей обработки, которая считывает данные из LL1 и выводит свои вычисления в новый связанный список. Из этого я должен выводить каждый новый связанный список потоков в файл SINGLE. Я пытаюсь вывести каждый связанный список в виде последовательных блоков, так что потоки не смешиваются данные, чтобы я использовал точку синхронизации следующим образом:Java-очередь потоков с пулом потоков

public synchronized void appendContents(List<Vector2> output1) { 
    try { 
     sFileName = outFilePath + "\\file" +fileCount+ ".cntr"; 
     File oFile = new File(sFileName); 
     if (!oFile.exists()) { 
      oFile.createNewFile(); 
     } 
     if (oFile.canWrite()) { 
      //BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName, true)); 
      FileWriter wstream = new FileWriter(oFile, true); 
      BufferedWriter outWriter = new BufferedWriter(wstream); 
      for(int i = 0; i < output1.size(); i++) 
      { 
       //replace the space marker values with a newline 
       if(output1.get(i).y == -200.0){ 
       outWriter.newLine(); 
       }else{ 
       outWriter.write(String.valueOf(output1.get(i).x) + " " + String.valueOf(output1.get(i).y) + " " + String.valueOf(interval)); 
       outWriter.newLine();  
       } 
      }   
      outWriter.close(); 
     } 
    } 
    catch (IOException oException) { 
     throw new IllegalArgumentException("Error appending/File cannot be written: \n" + sFileName); 
    } 

Проблема я столкнулся в том, что данные не выходит в порядке, который является то, что мне нужно есть

list1 value        list1 value 
list1 value   _______________\  list2 value 
list1 value   ________________\ list1 value 
list2 value   RATHER THAN ____/ list3 value 
list2 value   ---------------/  list2 value 
list2 value        list1 value 
list3 value        list2 value 
list3 value        list1 value 
list3 value        list3 value 
list3 value        list3 value 

Если кто-нибудь может дать мне шаг в правильном направлении, он будет высоко оценен. Спасибо,

Джек

+0

Показать, как вы начинаете свои темы. Также уточните, какой результат вы получаете и чего ожидаете. –

+0

Возможно, этот [пример] (http://arashmd.blogspot.com/2013/07/java-thread-example.html#fe) поможет –

+1

. Каков ресурс, который вам нужен для синхронизации доступа? Похоже, что это «Список ». Вероятно, вы должны заблокировать это, вместо использования неявной блокировки объекта, к которому принадлежит appendContents(). Как написано, в высококонкурентной среде ваш метод appendContents() может стать узким местом и ограничить масштабируемость. – scottb

ответ

2

Целью synchronized является синхронизация по общему ресурсу, так что только один Thread получает доступ к критической секции в один раз. Я собираюсь предположить, что вы создаете три экземпляра Thread, которые каждый вызов appendContents на свой собственный объект.

Метод неявно синхронизируется на this, но так как все три Thread s синхронизированы на другом объекте, т.е. другой this, ничто не блокирует их.

1

Как я понимаю, вы каждый раз запускаете новую задачу для каждого элемента списка?

тогда вы можете просто написать задание с возможностью вызова -> сохранить результат в Feature.Put Feature в списке vs result (resultFeatureFromList). и в конце сделать что-то вроде этого: Я использую функцию от Guava Lib;

Iterables.transform(resultList<Feature>,new Function(){ 
    public resultComputition apply(Feature resultFeatureFromList){ 
       return resultFeatureFromList.get(); 
    } 
}); 

Итак, в заключение вы выполните всю задачу в правильном порядке. и после вытягивания все просто ждут результата.

1

Разрабатывая из user2870704's answer, вы можете структурировать приложение следующим образом:

  • Есть нить прочитать содержимое файла;
  • Для каждого элемента в файле отправьте задание Callable в пул потоков;
  • Сохраните возвращенный Future в списке или списке списков - вы определяете необходимую гранулярность;
  • Открыть выходной файл в той же теме и просмотреть список результатов для записи.

В качестве примера:

void readAndOutput(String inputFilePath, String outputFilePath) { 
    List<List<Future<Result>>> results = readAndSpawnTask(inputFilePath); 

    PrintWriter out = new PrintWriter(new File(outputFilePath)); 

    for (List<Future<Result>> block : results) { 
     for (Future<Result> r : block) { 
      out.println(r.get().toString()); 
     } 
    } 

    out.flush(); 
    out.close(); 
} 


List<List<Future<Result>>> readAndSpawnTask(String path) { 
    List<List<Future<Result>>> results = new ArrayList<>(numOfBlocks); 
    BufferedReader in = new BufferedReader(new FileReader(new File(path))); 

    for (int i = 0; i < numOfBlocks; ++i) { 
     results.add(new LinkedList<Future<Result>>()); 
    } 

    for (String line = in.readLine(); line != null; line = in.readLine()) { 
     int respectiveBlock; 
     Callable<Result> task; 
     // Process line and convert it into a task of your own. 
     // Determine in which block the result goes into. 
     Future<Result> r = threadPool.submit(task); 
     results.get(respectiveBlock).add(r); 
    } 

    in.close(); 

    return results; 
} 

Если вы хотите и/или потребность параллелизм, идея заключается в том, чтобы получить доступ к файлам в одном потоке. Используя список Future, у вас есть гарантии написания результатов в правильном порядке, и ваш основной поток будет блокироваться до тех пор, пока нужный результат не будет готов.

Конечно, вам все равно придется учитывать возможные исключения, указанные в приведенном выше коде.

Смежные вопросы