ArrayList is Java’s resizable-array implementation of the List abstraction. It works well for ordinary list storage, but it does not synchronize concurrent access automatically. Multiple threads changing the same ArrayList can race, producing exceptions, stopped threads, or threads that remain alive without useful work. section 5.2.2
Investigate an ArrayList shared by producer and consumer threads by asking:
- Are size checks and modifications protected as one operation? section 5.2.2
- Do exceptions stop worker threads or leave zombie threads running? section 5.2.2
- Does VisualVM show abnormal CPU use, little memory activity, or unexpected thread states? section 5.2.2
A shared producer-consumer list
A Main class creates an ArrayList and starts two producers and two consumers. Producers test size before adding; consumers test size, read index 0, and remove it. Synchronizing each thread’s complete check-and-update sequence on Main.list prevents the competing operations from racing. section 5.2.2
Listing 5.3 The Main class creating and starting the producer and consumer threads
public class Main {
public static List<Integer> list = new ArrayList<>(); #1
public static void main(String[] args) {
new Producer().start(); #2
new Producer().start(); #2
new Consumer().start(); #2
new Consumer().start(); #2
}
}
Inspect the declaration that creates the shared ArrayList and starts the worker threads. section 5.2.2
