Concurrency practice questions

From OCP Java SE 8 (1Z0-809) · 23 questions on this topic

Concurrency practice questions from OCP Java SE 8 (1Z0-809). This pack has 23 questions tagged Concurrency, drawn from its timed mock exams. 8 of them are worked through in full below — the question, every option, why each is right or wrong, and the explanation.

Worked examples for Concurrency

  1. Question 1

    What is the output of the following program? ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { ExecutorService ex = Executors.newSingleThreadExecutor(); ex.shutdown(); System.out.println(ex.isShutdown()); } } ```

    1. A. trueCorrect answer

      Correct: shutdown flips isShutdown to true right away.

    2. B. An exception is thrown because no task was ever submitted

      An empty executor shuts down without complaint; no task submission is required.

    3. C. false

      isShutdown reflects that shutdown was called, so it is true; whether all work has finished is a separate state.

    4. D. The program never exits because shutdown blocks

      shutdown returns immediately without blocking.

    Explanation

    isShutdown becomes true immediately once shutdown is called, meaning no new tasks are accepted rather than that all work has finished. shutdown does not block, and an executor with no submitted tasks shuts down normally.

  2. Question 2

    Two threads each hold one lock and wait forever for the lock the other holds. What is this situation called?

    1. A. DeadlockCorrect answer

      Two threads each holding a lock and waiting forever for the lock the other holds is a circular wait with no progress, which is the defining condition of deadlock (Oracle Tutorial - Deadlock/Liveness).

    2. B. Race condition

      A race condition is order-dependent incorrect results arising from interleaving, not a mutual blocking on locks; here the threads are stuck rather than producing wrong output.

    3. C. Starvation

      Starvation is one thread being perpetually denied the resources it needs while others make progress, not two threads mutually blocking each other.

    4. D. Livelock

      Livelock is the busy variant in which threads keep responding to each other without progressing; here the threads are blocked and idle on their locks rather than actively responding.

    Explanation

    The defining condition is a circular wait: each thread holds a lock the other needs and neither will release until it acquires the other, so no thread ever proceeds. This permanent, mutual blocking on locks is deadlock, distinct from liveness failures where threads still run but make no useful progress. Spec: Oracle Tutorial, Deadlock/Liveness.

  3. Question 3

    What is the result of compiling the following program? ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { ExecutorService ex = Executors.newSingleThreadExecutor(); ex.execute(() -> 42); ex.shutdown(); } } ```

    1. A. It compiles; execute returns the 42 as a Future

      This describes submit, not execute. execute returns void and accepts only Runnable, so it cannot return a Future, and the value-returning lambda does not compile against it.

    2. B. It compiles and discards the 42

      This assumes the value-returning lambda is a valid Runnable whose result is simply ignored. It is not Runnable-compatible, so the code fails to compile rather than compiling and discarding a value.

    3. C. An exception is thrown at runtime

      This assumes the program runs and fails at runtime. The mismatch is caught by the compiler, so the failure is at compile time and no code executes.

    4. D. Compilation failsCorrect answer

      execute takes a Runnable, whose void-compatible body must be a statement expression; the bare literal 42 is not a statement expression, so the lambda cannot target Runnable and compilation fails (JLS 8 section 15.27.2).

    Explanation

    Executor.execute accepts only a Runnable, whose lambda body must be void-compatible, meaning a statement expression. The body () -> 42 is a bare literal expression, which is not a statement expression, so it cannot target Runnable and the code fails to compile. By contrast, submit would accept the same lambda as a Callable and return a Future. Spec: JavaDoc 8, Executor.execute; JLS 8 section 15.27.2.

  4. Question 4

    What is the output of the following program? ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Main { public static void main(String[] args) throws Exception { ExecutorService ex = Executors.newSingleThreadExecutor(); Future<?> f = ex.submit(() -> System.out.print("run")); System.out.println(f.get()); ex.shutdown(); } } ```

    1. A. Compilation fails because get() cannot be called on Future<?>

      get on a Future of unknown type returns Object and is perfectly callable.

    2. B. run

      After the task prints, get returns null, which println renders as additional text.

    3. C. runnullCorrect answer

      Correct: the Runnable's Future yields null, so the task output is followed by the printed null.

    4. D. runtrue

      A Runnable's Future completes with null, not a boolean true.

    Explanation

    A void-compatible lambda is submitted as a Runnable, so the returned Future completes with null. get blocks until the task has printed, then printing the null result appends the text null.

  5. Question 5

    What is the output of the following program? ```java import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream.of("a", "b", "c").parallel().forEachOrdered(System.out::print); System.out.println(); } } ```

    1. A. Some ordering of a, b, c that may vary between runs

      This describes plain forEach on a parallel stream. forEachOrdered specifically guarantees encounter order, so the output does not vary between runs.

    2. B. Compilation fails on a parallel stream

      This assumes forEachOrdered is invalid on a parallel stream. It is a legal terminal operation on parallel streams, so the code compiles.

    3. C. abcCorrect answer

      forEachOrdered honors the stream's encounter order even when parallel, so it prints the elements in source order, abc, on every run (JavaDoc 8 - Stream.forEachOrdered).

    4. D. cba

      This assumes parallel processing reverses the order. Encounter order is preserved, not reversed, so the output is the source order rather than its reverse.

    Explanation

    forEachOrdered processes elements in the stream's defined encounter order even when the stream is parallel, so the output matches the source sequence exactly. The elements were supplied in the order a, b, c, so the program always prints abc. The trade-off is reduced parallelism, but the ordering guarantee still holds. Spec: JavaDoc 8, Stream.forEachOrdered.

  6. Question 6

    What is the output of the following program? ```java import java.util.Arrays; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<Integer> l = new CopyOnWriteArrayList<>(Arrays.asList(1, 2, 3)); for (int i : l) { l.add(i + 10); } System.out.println(l.size()); } } ```

    1. A. It loops forever

      This assumes each added element feeds the ongoing loop. The iterator walks a fixed snapshot taken when iteration began, so the newly added elements are invisible to it and the loop runs a bounded number of times.

    2. B. A ConcurrentModificationException is thrown

      This applies ArrayList's fail-fast behavior. A CopyOnWriteArrayList iterates over a snapshot and never throws ConcurrentModificationException when the list is modified during iteration.

    3. C. 6Correct answer

      The iterator traverses the 3-element snapshot exactly three times, appending one element to the backing list each pass, so the list ends with three originals plus three additions, a size of 6 (JavaDoc 8 - CopyOnWriteArrayList).

    4. D. 3

      This assumes the adds do not take effect. They do modify the backing list; they are merely invisible to the in-progress snapshot iterator, so the final size is more than the original three.

    Explanation

    A CopyOnWriteArrayList iterator traverses a snapshot captured when iteration begins, so elements added during the loop are neither seen by the iterator nor cause a ConcurrentModificationException. The loop runs exactly three times over the original elements, appending one element to the backing list each iteration. The list therefore ends with the three originals plus three additions, for a size of six. Spec: JavaDoc 8, CopyOnWriteArrayList.

  7. Question 7

    What is the output of the following program? ```java import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Main { public static void main(String[] args) throws Exception { ExecutorService ex = Executors.newSingleThreadExecutor(); Future<Integer> f = ex.submit(() -> { if (true) { throw new IllegalStateException("boom"); } return 1; }); try { f.get(); } catch (ExecutionException e) { System.out.println("wrapped " + e.getCause().getMessage()); } ex.shutdown(); } } ```

    1. A. wrapped boomCorrect answer

      Correct: get rethrows the task's failure wrapped in ExecutionException, whose cause carries the original message.

    2. B. An IllegalStateException propagates directly out of get()

      The task's exception does not propagate directly; get wraps it in ExecutionException.

    3. C. The program hangs forever

      The task finished, exceptionally, so get does not hang.

    4. D. wrapped null

      The cause is the original exception with its message, not null.

    Explanation

    An exception thrown inside a task does not surface on the worker thread; Future.get rethrows it wrapped in an ExecutionException whose cause is the original. Because the task completed exceptionally, get returns promptly with that wrapper.

  8. Question 8

    Which of the following statements about concurrent collections are true?

    1. A. ConcurrentHashMap rejects null keys and null valuesCorrect answer

      ConcurrentHashMap forbids null keys and null values, because in a concurrent map a null cannot be distinguished from an absent mapping (JavaDoc 8 - ConcurrentHashMap).

    2. B. Using concurrent collections removes any need for other synchronization in a program

      Concurrent collections protect only their own internal state, not compound application logic; multi-step operations across a collection still need external synchronization, so they do not remove every need for other synchronization.

    3. C. A CopyOnWriteArrayList iterator reflects writes made after the iterator was created

      A CopyOnWriteArrayList iterator traverses a fixed snapshot taken when it was created, so writes made after that point are not reflected in the iteration.

    4. D. Iterating a Collections.synchronizedList still requires manual synchronization to be safeCorrect answer

      A synchronized wrapper guards only individual method calls, but an iteration spans many calls, so it still requires holding an external lock on the list to be safe (JavaDoc 8 - Collections.synchronizedList).

    Explanation

    ConcurrentHashMap forbids null keys and values because a null is indistinguishable from an absent mapping, and a synchronized wrapper makes only each individual method call atomic, so an iteration that spans many calls still needs an external lock. By contrast, a copy-on-write iterator sees a fixed snapshot and never reflects later writes, and concurrent collections guard only their own state rather than compound application logic. Spec: JavaDoc 8, ConcurrentHashMap, CopyOnWriteArrayList, Collections.synchronizedList.

Practise all 23 Concurrency questions

OCP Java SE 8 has the full set, inside timed mock exams that mirror real exam conditions — every question with a worked explanation.

Open OCP Java SE 8

Other topics in this pack