带线程池的Java线程队列

时间:2013-10-10 04:41:53

标签: java multithreading input linked-list output

我制作了一个程序,它使用单个线程将文件中的数据读入链表,然后将其称为LL1。从这里我创建了一个线程池,它为每个线程分配一个处理任务,该任务从LL1读取数据并将其计算输出到新的链表。 从这里我需要将每个线程新的链表输出到一个SINGLE文件中。我试图在顺序块中输出每个链表,以便线程不混合数据,所以我使用了一个同步点,如下所示:

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

如果有人能够朝着正确的方向迈出一步,我们将不胜感激。 谢谢,

杰克

3 个答案:

答案 0 :(得分:2)

synchronized的目的是在共享资源上进行同步,以便一次只有一个Thread可以访问关键部分。我将假设您正在生成三个Thread个实例,每个实例都在自己的对象上调用appendContents

synchronized方法隐式地在this上同步,但由于所有三个Thread都在不同的对象上同步,即。一个不同的this,没有任何一个阻止它们。

答案 1 :(得分:1)

据我了解,每次为每个列表元素执行新任务时都会运行?

然后你就可以编写Callable任务 - &gt;将结果保存在List vs result(resultFeatureFromList)中的Feature.Put Feature中。最后做一些像这样的事情: 我使用来自Guava Lib的函数;

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

总而言之,您将以正确的顺序运行所有任务。拉完后只需等待结果。

答案 2 :(得分: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列表,您可以保证以正确的顺序编写结果,并且主线程将阻塞,直到所需的结果准备就绪。

当然,您仍然需要考虑上述代码中引发的可能异常。