Creating Java Threads and Fundamental Thread Operations

Processes and Threads

A process represents an instance of a program. Some programs can have multiple instances, such as a web browser; others are limited to one, like a music player.

A thread is a single flow of control within a process. It is the smallest unit of scheduling and resource allocation in Java (in Windows, a process is primarily a container for threads and is not directly executed).

Comparing processes and threads from resource usage and communication aspects:

  • Processes have independent memory spaces and communicate via IPC mechanisms. Threads within the same process share memory (heap and method area) but have their own stack and program counter.
  • Communication between threads is more straightforward and efficient then inter-process communication.

Applications

Asynchronous invocation: In synchronous calls, the caller waits for the operation to complete. In asynchronous calls, the caller continues without waiting, improving responsiveness.

Efficiency improvement: Multi-threading can improve CPU utilization, especially when tasks involve I/O operations that otherwise cause idle CPU time.

Considerations

  1. On a single-core CPU, multi-threading allows interleaved execution, preventing one task from monopolizing the CPU.
  2. On multi-core systems, parallelism may or may not improve efficiency depending on task divisibility (Amdahl's Law) and overhead.
  3. I/O operations typically do not consume CPU cycles but often use blocking I/O, forcing the thread to wait. Non-blocking and asynchronous I/O can better utilize CPU resources.

Core Java Thread Concepts

3.1 Creating Threads

Method 1: Extending Thread and Overriding run

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            @Override
            public void run() {
                log.warn("running");
            }
        };
        t.setName("thread1");
        t.start();
        log.warn("running");
    }
}

Method 2: Using Runnable Enterface (Preferred)

This separates the task from the thread, following composition over inheritance.

@Slf4j(topic = "c.Test2")
public class Test2 {
    public static void main(String[] args) {
        Runnable r = () -> log.warn("running");
        new Thread(r, "thread1").start();
        log.warn("running");
    }
}

Comparison: Both methods ultimately modify the run() method. In method 2, the Runnable target is stored in Thread.target and invoked in Thread.run(). Using Runnable is more flexible and works seamlessly with thread pools.

Method 3: FutureTask for Returning Results

When a thread needs to return a result, use Callable with FutureTask.

@Slf4j(topic = "c.Test3")
public class Test3 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        FutureTask<Integer> task = new FutureTask<>(() -> {
            log.warn("Running");
            Thread.sleep(1000);
            return 100;
        });
        Thread t = new Thread(task, "t1");
        t.start();
        log.warn("{}", task.get());
    }
}

3.2 Internal Thread Mechanics

  • Stack and Stack Frames: Each thread has its own stack. Each method call pushes a stack frame; the top frame is the active frame.
  • Thread Context Switch: Occurs due to garbage collection, time slice expiration, higher-priority threads, or explicit calls like sleep(), yield(), wait(), join(), park(), or lock contention.

3.3 Common Thread Methods

Method Description
start() / run() start() creates a new thread and makes it runnable. run() executes code in the current thread.
sleep(long millis) Causes the thread to enter TIMED_WAITING state.
yield() Hints that the thread is willing to yield its CPU; the scheduler may ignore this.
join() Waits for the thread to die.
interrupt() Interrupts the thread (wakes it from blocking or sets the interruption flag).
stop(), suspend(), resume() Deprecated due to safety issues; use a two-phase termination pattern.

interrupt() Usage:

@Slf4j(topic = "c.Test4")
public class Test4 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    log.warn("break the loop");
                    break;
                }
            }
        }, "t1");
        t1.start();
        Thread.sleep(1000);
        log.warn("interrupt t1");
        t1.interrupt();
    }
}

Combining interrupt() with LockSupport.park():

@Slf4j(topic = "c.Test7")
public class Test7 {
    public static void main(String[] args) throws InterruptedException {
        log.warn("main thread");
        parkTest();
    }

    private static void parkTest() throws InterruptedException {
        Runnable r = () -> {
            log.warn("park...");
            LockSupport.park();
            log.warn("unpark...");
            log.debug("interrupted state: {}", Thread.interrupted());
        };
        Thread t1 = new Thread(r, "t1");
        t1.start();
        Thread.sleep(1000);
        t1.interrupt();
    }
}

Note: After interrupting a parked thread, Thread.interrupted() clears the flag; otherwise, subsequent park() calls might be ineffective.

Two-Phase Termination Pattern (Replacement for stop()):

@Slf4j(topic = "c.TwoStageTermination")
class TwoStageTermination {
    private Thread monitor;

    public void start() {
        monitor = new Thread(() -> {
            while (true) {
                Thread current = Thread.currentThread();
                if (current.isInterrupted()) {
                    log.warn("monitor stopping");
                    break;
                }
                try {
                    Thread.sleep(2000);
                    log.warn("monitor running check...");
                } catch (InterruptedException e) {
                    current.interrupt(); // re-set flag
                }
            }
        }, "monitor_thread");
        monitor.start();
    }

    public void stop() {
        monitor.interrupt();
    }
}

Daemon Threads: A daemon thread does not prevent the JVM from exiting. Once all user threads finish, the JVM terminates regardless of daemon thread state. Examples: garbage collector, Tomcat acceptor/poller threads.

3.4 Thread States

From OS perspective: New, Runnable (ready), Running, Blocked, Terminated.

From Java perspective (Thread.State enum):

State Description
NEW Created but not started.
RUNNABLE Includes OS runnable and runing states, also covering some brief blocking for I/O.
BLOCKED Waiting for a monitor lock (e.g., synchronized).
WAITING Waiting indefinitely (e.g., join(), park()).
TIMED_WAITING Waiting with a timeout (e.g., sleep(), join(long)).
TERMINATED Thread has completed execution.

3.5 Practical Example: Making Tea Concurrently

A simplified scenario where two threads prepare tea in parallel:

Sleeper Utility:

public class Sleeper {
    public static void sleep(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Main Logic:

@Slf4j(topic = "c.Test8")
public class Test8 {
    public static void main(String[] args) {
        Thread cookWater = new Thread(() -> {
            log.warn("Wash kettle");
            Sleeper.sleep(1);
            log.warn("Boil water");
            Sleeper.sleep(15);
            log.warn("Water ready");
        }, "cookWater");

        Thread prepareTea = new Thread(() -> {
            log.warn("Wash teapot");
            Sleeper.sleep(1);
            log.warn("Wash cups");
            Sleeper.sleep(2);
            log.warn("Get tea leaves");
            Sleeper.sleep(1);
            log.warn("Teaware ready");
            try {
                cookWater.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.warn("Brew tea");
        }, "prepareTea");

        cookWater.start();
        prepareTea.start();
    }
}

The join() call ensures tea is brewed only after the water is boiled.

Tags: java multithreading thread creation thread states Interrupt

Posted on Mon, 13 Jul 2026 17:22:18 +0000 by echo64