導入
そのような小さな要件があります:
- 500のタスクがあり、最初にこれらの500のタスクを50のグループに分割し、次に合計10のグループを分割できます。次に、これらの10グループのタスクをスレッドプールにループします(現在、スレッドプールには10グループのタスクがあります)
- スレッドプールは、これらの10グループのタスクを個別に処理します。
記述された擬似コードは次のとおりです。
array = 500个任务;
JSONArray perThread = new JSONArray();
int count = 0;
for(int i = 0; i < 10; i++){
//积攒50个一组,攒满了就开一个线程。
for(50次){
perThread.add(array.get(count));
count++;
}
if (perThread.size() == 50) {
//下面一行代码是启动一个线程池中的线程,执行每一组(50个)任务
threadPool.submit(()->sendOpenAPI(perThread));
//清空该组,重新填充。
perThread.clear();
}
}
上記のコードの何が問題になっているのかを慎重に考えてください。
問題を分析する
オブジェクト参照(つまり、変数perThread)が子スレッドに渡されます。子スレッドが実行されている場合、メインスレッドはブロックされませんが、実行を継続します。実行する
perThread.clear()
このコード行で、オブジェクト参照(perThread)がクリアされます。その後、子スレッドのperThreadはなくなります。これは髪も扱います。。。。
解決
ディープコピーを使用すると、この問題が解決します。そのコードブロックを次のように適応させます。
if (perThread.size() == 50) {
//开新线程。
JSONArray deepCopy = new JSONArray(); //对原来的对象进行深拷贝。
BeanUtils.copyProperties(perThread,deepCopy);
threadPool.submit(()->sendOpenAPI(deepCopy));
perThread.clear(); //放心清空即可,反正已经将深拷贝后的东西传入子线程了
}
ディープコピーを使用すると、子スレッドで新しいオブジェクト参照が使用されます。メインスレッドで元のオブジェクト参照が空になっても、子スレッドに新しいメモリスペースがあるため、オブジェクトは空になりません。
問題が解決しました。