如何跨多个线程

时间:2015-12-28 09:00:19

标签: java multithreading concurrency

我有一个程序可以处理来自Excel电子表格的记录。现在,处理大量记录需要很长时间(让我们说100,000个)。

这是我班级到目前为止的样子:

public class RecordProcessor{
    private Map<Integer, String> statusMap = new HashMap<Integer, String>();
    private List<Record> allRecordsToBeProcessed = new ArrayList<Record>();


    public static void main(String args[]){

         RecordProcessor processor = new RecordProcessor();

         processor.loadWorkbook();

         processor.processRecords();

         processor.writeOutput();

    }

    public void loadWorkbook(String excelPath){

         /**********************************
           1. Load the excel worksheet
           2. Populate all records into the allRecordsToBeProcessed object
         **********************************/

    }


    public void processRecords(){

          /**********************************
            Do the actual processing here.
          **********************************/
          int rowNumber= -1;

          for(Record record:allRecordsToBeProcessed){
               rowNumber++;
               String processingStatus = processRecord(record);
               this.statusMap.put(counter, processingStatus);
          }

    }

    private String processRecord(Record record){

           //Do something to process this record
          //Return either "SUCCESS" or a particular failure message

    }

    public void writeOutput(){
       //Write the output to the excel sheet

       for(int rowIndex:this.statusMap.keySet()){

           //Write this.statusMap.get(rowIndex) in row with Index rowIndex
       }
    }
}

我想要做的是将处理拆分为每个1,000个单独的线程,这样我就可以节省时间。因此,实际上,我将拥有100个线程,每个线程处理1000条记录。

这里的另一个要求是,我要在excel表格中的每一行更新一个单元格,表明该处理是否通过了该特定记录。

这是我能做的:

  1. 我可以编写一个名为loadAndPaginate()的方法,它将所有记录分成许多List<Record>个对象,每个对象包含1,000条记录(而不是只有一个包含所有100,000条记录的列表)

  2. 我可以创建一个实现Runnable接口的类,并在该实现中使用public String processRecord(Record record)方法

  3. 然后我可以从这个可运行的实现创建所需数量的线程并调用start()方法

  4. 我知道这将处理100,000条记录并大大缩短处理时间。但是,我不知道该怎么做,是如何更新我的Excel工作表中的状态?

    我基本上必须从同时运行的这些线程中更新我的类中的this.statusMap(如上所示)。

    我尝试了以下内容:

    • 从我的调用类初始化this.statusMap并将其作为构造函数值传递给我的Runnable实现,但我得到的是一张从未更新过的地图。
    • 其他原始方法,比如每个线程写入一个文件,其中包含他们处理的所有记录的状态,并让我的主线程读取这些文件并在所有线程停止运行后将状态写入excel(我对该方法不满意)

    有人可以指导我正确的设计吗?

    编辑我的问题以回应Jarrod的评论

    很抱歉,如果我的问题太宽泛了。我试图让它变得清脆。

    这就是我想要实现的目标

     public class RecordProcessor{
    
           private Map<Integer, String> statusMap = new HashMap<Integer, String>();
    
           private List<List<Record>> paginatedRecords;
    
           //Let's assume I populate the above list like a List having 100 List<Record> that have 1000 Record objects each
    
           public void processRecords(){
                int i=-1;
                for(List<Record> records:this.paginatedRecords){
                     i++;
    
                     //The `RecordProcessorImpl` implements the `Runnable` interface and its `run()` method contains my logic to process a List of records
                     RecordProcessorImpl impl = new RecordProcessorImpl(records, this.statusMap);
    
                     Thread t = new Thread(impl, "ProcessorThread-" + i);
                     t.start();
                }
           }
    
     }
    

    最后,我想要更新我需要为Excel表格中的所有记录编写的所有状态this.statusMap

    我上面列出的方法并不奏效。我的问题是如何从多个线程写入this.stautsMap

    我希望这次能够准确无误。

    谢谢, 斯利拉姆

1 个答案:

答案 0 :(得分:1)

如果您希望statusMap可全局访问,则可以将其设为

public static Map<Integer, String> statusMap = new HashMap<Integer, String>();

现在可以通过RecordProcessor.statusMap

访问它

此解决方案的问题在于,它不是thread safe。幸运的是,Java提供了一个带有ConcurrentHashMaps的线程安全的HashMap。所以实现可能看起来像

public static Map<Integer, String> statusMap = new ConcurrentHashMap<Integer, String>();

当然,如果您愿意,可以封装statusMap。

RecordProcessorImpl impl = new RecordProcessorImpl(records);

在您的RecordProcessorImpl中,您现在可以使用RecordProcessor.statusMap访问地图,如上所述。