LoginSignup
2
2

More than 3 years have passed since last update.

スレッドセーフなリスト

Posted at

並列処理怖いよって話

リストについて基本的に注意すべきですが、こと並列処理に関しては
マルチスレッドに要注意です

たとえば

だめ.java
    private static List<String> list = new ArrayList<>();

    private static Consumer<Integer> qwe = v -> list.add(String.format("%s: %s", Instant.now(), v));

    public static void main(String[] args) {
        IntStream.range(0, 9).boxed().collect(Collectors.toList()).parallelStream().forEach(qwe);
        list.forEach(System.out::println);
    }

これの結果は

null
null
null
2019-11-08T17:37:22.279Z: 7
2019-11-08T17:37:22.313Z: 3
2019-11-08T17:37:22.313Z: 0
2019-11-08T17:37:22.313Z: 4
2019-11-08T17:37:22.313Z: 6
2019-11-08T17:37:22.313Z: 8

とか

2019-11-08T17:37:48.381Z: 7
2019-11-08T17:37:48.381Z: 5
2019-11-08T17:37:48.381Z: 2
2019-11-08T17:37:48.416Z: 0
2019-11-08T17:37:48.416Z: 8
2019-11-08T17:37:48.417Z: 4
2019-11-08T17:37:48.417Z: 3
2019-11-08T17:37:48.417Z: 6

とか、もうめちゃくちゃです
なにnullってw
listにaddするタイミングで同時にやろうとして
よくわからんくなって障害起きてるわけですね

なので...

これでよし.java
    private static List<String> list = Collections.synchronizedList(new ArrayList<>());

    private static Consumer<Integer> qwe = v -> list.add(String.format("%s: %s", Instant.now(), v));

    public static void main(String[] args) {
        IntStream.range(0, 9).boxed().collect(Collectors.toList()).parallelStream().forEachOrdered(qwe);
        list.forEach(System.out::println);
    }

スレッドセーフなsynchronizedListを使い
かつ順番を整えるためにforEachorderedを使ってaddしました
ラムダのforEachは順次でやってくれているのでsysoutしてるとこはそのままで

2019-11-08T17:40:22.228Z: 0
2019-11-08T17:40:22.259Z: 1
2019-11-08T17:40:22.259Z: 2
2019-11-08T17:40:22.260Z: 3
2019-11-08T17:40:22.260Z: 4
2019-11-08T17:40:22.260Z: 5
2019-11-08T17:40:22.260Z: 6
2019-11-08T17:40:22.260Z: 7
2019-11-08T17:40:22.260Z: 8

って、綺麗にやってくれます

一言でいうと

同時に変更したらコンフリクトするやんけ!やめろ!ってことですね
注意しておけばスレッドセーフなものに切り替えるだけで良い感じでしょうか

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2