⏱️
Dartでループ内の処理を並列処理する方法
使い所
ループ内で各プロセスを逐次処理する必要はないが、ループ全体の完了を待ちたい時。
例えば、複数のファイルを読み込んでから後続処理を行いたい場合、それぞれのダウンロード処理で逐次処理を行うと、待ち時間がファイル数に比例して増加してしまいます。
この場合、ダウンロードを並列に処理して大幅に待ち時間を短縮しつつ、全てのダウンロードを待つことで、後続処理への影響も防げます。
対応方法
await Future.wait(futures)
を使うことで、並列処理しつつ全体の完了を待つことができます。
実装例
ループ内の処理をList<Future<*>>
型変数に格納してFuture.wait()
で実行する。
処理時間:4.3秒
code
import 'dart:math' as math;
void main() async {
List<Future<void>> futures = [];
for (int i = 0; i < 10; i++) {
futures.add(Future(() => process(i)));
}
await Future.wait(futures);
print("done");
}
Future<void> process(final int index) async {
final waitingSecond = math.Random().nextInt(3);
await Future.delayed(Duration(seconds: waitingSecond));
print('process $index');
}
result
process 2
process 3
process 4
process 6
process 9
process 7
process 0
process 1
process 5
process 8
done
補足
単純にawaitする場合
各プロセスが一件ずつ処理されるので、時間がかかります。
処理時間:19.8秒
cord
...
void main() async {
for (int i = 0; i < 10; i++) {
await process(i);
}
print("done");
}
...
result
process 0
process 1
process 2
process 3
process 4
process 5
process 6
process 7
process 8
process 9
done
そもそもawaitしない場合
処理自体は早く終わりますが、後続処理が先に実行されてしまいます。
処理時間:4.3秒
cord
...
void main() {
for (int i = 0; i < 10; i++) {
process(i);
}
print("done");
}
...
result
done
process 0
process 3
process 9
process 2
process 4
process 6
process 8
process 1
process 5
process 7
参照情報
Discussion