×

java · level 3 · unit 5 · lesson 4

  1. meet it
  2. guess first
  3. your turn
  4. fix it
  5. nailed it

Tap a green word if you get lost.

meet it

A is a map, one change at a time.

A plain HashMap is not thread-safe: two threads writing at once can lose entries or tangle its insides. A ConcurrentHashMap is built for sharing. Each single call, like put or get, is safe however many threads use it.

Two calls together are not safe. counts.put(word, counts.getOrDefault(word, 0) + 1) is : another thread can change the count between the read and the write. Use one call instead: adds 1, or starts at 1, atomically.

A ConcurrentHashMap keeps no order. For a report, copy it into a TreeMap once the threads have finished: new TreeMap<>(counts).

import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
public class Main {
    static void tally(Map<String, Integer> counts, List<String> words) {
        for (String word : words) {
            counts.merge(word, 1, Integer::sum);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Map<String, Integer> counts = new ConcurrentHashMap<>();
        List<String> pageOne = List.of("to", "be", "or", "not", "to", "be");
        List<String> pageTwo = List.of("that", "is", "the", "question");
        Thread a = new Thread(() -> tally(counts, pageOne));
        Thread b = new Thread(() -> tally(counts, pageTwo));
        a.start();
        b.start();
        a.join();
        b.join();
        System.out.println(new TreeMap<>(counts));
    }
}

Integer::sum is the rule merge uses to combine the old count with the new 1.