2013-10-10 188 views
0

我制作了一个程序,它使用单线程将文件中的数据读入链接列表让我们称之为LL1。从这里我做了一个线程池,它为每个线程分配一个处理任务,它从LL1读取数据并将其计算结果输出到一个新的链表中。 从这我需要输出每个线程新的链接列表成一个单一的文件。我试图输出连续的块,每个块链表,使线程不混合的数据,所以我使用了一个同步点如下:带线程池的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)将帮助 – 2013-10-10 05:29:12

+1

您需要同步访问权限的资源是什么?它似乎可能是'List '。您应该锁定它,而不是使用appendContents()所属对象的隐式锁定。正如所写,在高度并发的环境中,appendContents()方法可能会成为瓶颈并限制可伸缩性。 – scottb

回答

2

的​​目的是共享资源同步,以便只有一个Thread获得在单一时间访问临界区。我将假设您产生了三个Thread实例,每个实例都对其自己的对象调用appendContents

A​​方法隐式地在this上同步,但是因为所有三个Thread都在不同的对象上同步,不同的this,没有任何阻止他们。

1

据我所知,你每次运行每个列表元素的新任务?

然后您可以编写Callable任务 - >将结果保存在List vs result(resultFeatureFromList)中的Feature.Put Feature中。并在最后做出这样的事情: 我使用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列表,您可以保证以正确的顺序编写结果,并且您的主线程将会阻塞,直到所需的结果准备就绪。

当然,您仍然必须考虑上述代码中可能出现的异常。