私の入力データは、1 つのリストに 50,000 件 (またはそれ以上) の電子メール メッセージがあり、to、cc および bcc に複数の受信者が含まれているため、大量の重複があります。したがって、このリストから一意のメッセージを抽出する必要があります。
Message の特定のプロパティ (From、To リスト、contain(文字列のみ)) を比較して、同じかどうかを識別する必要があります。
現在、私はこの 50,000 件のメッセージを 50 個の小さな 1000 件のメッセージ リストに分割し、それぞれの小さなリストの複製をそのスレッドで実行しています。
すべてのスレッドがその出力を 1 つのリストに追加し、最後にそのスレッドの重複をチェックします。そうしているうちに、私の JVM は 1.25 GB のメモリに到達します。
したがって、50,000 を超えるメッセージをプッシュしようとすると、メモリ不足エラーが発生します。
と呼ばれるメソッドがremoveDeduplicate(array of messages, blank list)
あります。これは、メッセージの配列と空のリストを入力として受け取り、その空のリストに一意のメッセージを返します。これは私のコードです:
public Message[] processForDeduplication(Message[] msgs) throws MessagingException, IOException, InterruptedException {
final List<Message> output = new ArrayList<Message>();
if(msgs.length < MAX_MSG){
output.addAll(removeDeduplication(msgs, new ArrayList<Message>()));
} else {
List<Thread> threads = new ArrayList<Thread>();
int index = 0, lastIndex = MAX_MSG;
while(index < msgs.length){
if(lastIndex >= msgs.length) {
lastIndex = msgs.length;
}
final Message[] temp = Arrays.copyOfRange(msgs, index, lastIndex);
Thread t = new Thread(new Runnable(){
@Override
public void run() {
try {
output.addAll(removeDeduplication(temp, new ArrayList<Message>()));
} catch (MessagingException ex) {
logger.error(EmailComparator.class.getName() + ex);
} catch (IOException ex) {
logger.error(EmailComparator.class.getName() + ex);
}
}
});
t.start();
threads.add(t);
index = lastIndex;
lastIndex = lastIndex + MAX_MSG;
}
for(Thread t: threads){
while(t.isAlive()){
Thread.sleep(100);
}
}
threads = null;
}
List<Message> results = removeDeduplication(convertToArray(output), new ArrayList<Message>());
return convertToArray(results);
}
メモリの強化とパフォーマンスのためにコードを微調整しようとしています。現在、50,000 レコードを完了するのに約 12 ~ 15 秒かかります。これを 5 ~ 6 秒にしたいと考えています。