Java Level 4 Test

Naveen AnamaneniUpdated · 10 min read

One cashier serving one queue is easy to understand. Four cashiers sharing one cash drawer is where the trouble starts: two people reach for the same note, someone waits for a drawer that never opens, and the till is short at the end of the day. Most of this level of the course was about that second shop: threads, locks, executors and virtual threads, plus the JVM underneath and the newer language features. This test checks that you can spot the trouble before it happens.

How the Test Works

  • What's in it: 20 multiple-choice questions, then 3 puzzles where you work out what a short program prints (and, once, how to fix it).
  • Time: 30 minutes, without notes, an IDE or JShell.
  • Pass mark: 16 out of 23. The quiz marks the 20 questions for you. Mark the puzzles yourself, one point each, and add them to your quiz score.
  • What it covers: the lessons from "Multithreading in Java" to the newest platform features.

Part 1: 20 Questions

Level 4 test: 20 questions

20 questions
1What happens if you call t.run() instead of t.start()?
2What happens if you call start() twice on the same Thread?
3What is the key difference between sleep() and wait()?
4How do you call a private method through reflection?
5Is count++ on a volatile int count safe from many threads?
6What is a common way to prevent deadlock?
7Which is the modern way to send an HTTP GET and read the body as a String?
8How does Callable differ from Runnable?
9What does executor.shutdown() do?
10Which is best for a counter that many threads update under heavy contention?
11Does ConcurrentHashMap allow null keys or values?
12A JDBC Connection starts in auto-commit mode. How do you run two updates as one transaction?
13How should virtual threads be used?
14Where is a local variable int x inside a method stored?
15Since Java 8, where is class metadata stored?
16A pattern-matching switch has a default branch but no case null. What happens when the selector is null?
17What is the default garbage collector in modern JDKs (since Java 9)?
18In the class loader delegation model, a loader first:
19What does if (obj instanceof Point(int x, int y)) do?
20What is the main reason to prefer PreparedStatement over Statement?

Part 2: Output Puzzles

Work out each answer on paper before you open the solution. The solution shows a full program, its real output and a Try it button. Give yourself one point for each puzzle you get right.

Puzzle 1: Calling Run Before Start

What is printed?

Java
Thread t = new Thread(() -> System.out.print("A"));
t.run();
System.out.print("B");
t.start();
t.join();
System.out.print("C");
Show solution
RunStartPuzzle.java▶ Try it
public class RunStartPuzzle {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> System.out.print("A"));
        t.run();
        System.out.print("B");
        t.start();
        t.join();
        System.out.print("C");
        System.out.println();
    }
}
Output
ABAC
Why this output?

t.run() is a normal method call, so the main thread prints the first A. Then B. t.start() runs the same code in a new thread, which prints the second A, and join() waits for it to finish before C is printed. So the order is always the same. Revise: Calling Thread.run() Directly vs Thread.start().

Puzzle 2: Two Threads, One Counter

What is printed, and how do you fix it?

Java
int[] count = {0};
Runnable task = () -> {
    for (int i = 0; i < 10_000; i++) count[0]++;
};
Thread t1 = new Thread(task), t2 = new Thread(task);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(count[0]);

The answer to this one is not a single number, so the solution shows the fixed program instead.

Show solution
CounterFixed.java▶ Try it
import java.util.concurrent.atomic.AtomicInteger;
 
public class CounterFixed {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger count = new AtomicInteger();
        Runnable task = () -> {
            for (int i = 0; i < 10_000; i++) {
                count.incrementAndGet();
            }
        };
        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count.get());
    }
}
Output
20000
Why this output?

The original usually prints less than 20000, and a different number on each run. count[0]++ is three steps: read, add one, write. When both threads read the same value, one update is lost. Give yourself the point if you said "less than 20000, it varies" and named a fix: an AtomicInteger with incrementAndGet(), as above, or a synchronized block around the increment. Revise: Race Conditions and Thread Safety.

Puzzle 3: A Sealed Switch

What is printed?

Java
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}
 
static String describe(Shape s) {
    return switch (s) {
        case Circle c when c.r() > 10 -> "big circle";
        case Circle c -> "circle";
        case Square(double side) -> "square " + side;
    };
}
 
// in main:
System.out.println(describe(new Circle(5)) + ", "
        + describe(new Square(2)));
Show solution
ShapePuzzle.java▶ Try it
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}
 
public class ShapePuzzle {
    static String describe(Shape s) {
        return switch (s) {
            case Circle c when c.r() > 10 -> "big circle";
            case Circle c -> "circle";
            case Square(double side) -> "square " + side;
        };
    }
 
    public static void main(String[] args) {
        System.out.println(describe(new Circle(5)) + ", "
                + describe(new Square(2)));
    }
}
Output
circle, square 2.0
Why this output?

A radius of 5 fails the guard c.r() > 10, so the next case, plain Circle c, matches. For the square, the record pattern pulls out side as a double, so 2 prints as 2.0. No default is needed, because the interface is sealed and both types are covered. Revise: Guards in Switch (When Clause).

What Your Score Means

Score (out of 23)What it meansWhat to do next
20 to 23You are ready for real-world JavaMove on to Build Tools in Java: Maven and Gradle
16 to 19A pass, with a few gapsRead the lessons linked from the questions you missed, then move on
Under 16Not yetReread the lessons behind your wrong answers, especially the concurrency ones, and take the test again

Was this tutorial helpful?