When you pass data from one thread to another thread, you need a thread-safe data structure. As you correctly pointed out, HashMap
is not thread-safe. For thread-safe collections in Java, look at the java.util.concurrent package. One of the simplest ways how to implementing a producer-consumer patterns is with LinkedBlockingQueue
.
Here is a complete example with two threads, one producing objects, the other one consuming and printing something every 100 objects:
AtomicBoolean finished = new AtomicBoolean(false);
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
String createdObject = Integer.toString(i);
queue.offer(createdObject);
}
finished.set(true);
});
Thread thread2 = new Thread(() -> {
int count = 0;
while (!finished.get() || !queue.isEmpty()) {
try {
String object = queue.poll(100, TimeUnit.MILLISECONDS);
if (count++ % 100 == 0) {
System.out.println(object);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread1.run(); thread2.run();
thread1.join(); thread2.join();
You may notice one thing - apart from the produced items, the threads also need to exchange other information - when the producer is finished. Again, you cannot safely exchange this information without synchronization. You can use AtomicBoolean
as in the example, or a volatile
field.