我有一个程序可以处理来自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表格中的每一行更新一个单元格,表明该处理是否通过了该特定记录。
这是我能做的:
我可以编写一个名为loadAndPaginate()
的方法,它将所有记录分成许多List<Record>
个对象,每个对象包含1,000条记录(而不是只有一个包含所有100,000条记录的列表)
我可以创建一个实现Runnable
接口的类,并在该实现中使用public String processRecord(Record record)
方法
然后我可以从这个可运行的实现创建所需数量的线程并调用start()
方法
我知道这将处理100,000条记录并大大缩短处理时间。但是,我不知道该怎么做,是如何更新我的Excel工作表中的状态?
我基本上必须从同时运行的这些线程中更新我的类中的this.statusMap
(如上所示)。
我尝试了以下内容:
this.statusMap
并将其作为构造函数值传递给我的Runnable
实现,但我得到的是一张从未更新过的地图。有人可以指导我正确的设计吗?
编辑我的问题以回应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
?
我希望这次能够准确无误。
谢谢, 斯利拉姆
答案 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
访问地图,如上所述。