Skip to content

Creating New Threads

Java language has built-in support for multithreading. When a Java program starts, it actually launches a JVM process, and the JVM starts the main thread to execute the main() method. Within the main() method, we can start additional threads.

Creating a New Thread

Creating a new thread is very straightforward. We need to instantiate a Thread object and then call its start() method:

java
// Multithreading
public class Main {
    public static void main(String[] args) {
        Thread t = new Thread();
        t.start(); // Start a new thread
    }
}

However, this thread will do nothing and terminate immediately after starting. We want the new thread to execute specific code. There are several ways to achieve this:

Method 1: Extend the Thread Class and Override the run() Method

java
// Multithreading
public class Main {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start(); // Start a new thread
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Start new thread!");
    }
}

When executing the above code, note that the start() method internally calls the instance’s run() method automatically.

Method 2: Pass a Runnable Instance When Creating the Thread

java
// Multithreading
public class Main {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start(); // Start a new thread
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Start new thread!");
    }
}

Or, using the lambda syntax introduced in Java 8 for further simplification:

java
// Multithreading
public class Main {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("Start new thread!");
        });
        t.start(); // Start a new thread
    }
}

Question: Does using a thread to execute a print statement differ from executing it directly in the main() method?

Answer: Yes, there is a significant difference. Consider the following code:

java
public class Main {
    public static void main(String[] args) {
        System.out.println("Main start...");
        Thread t = new Thread() {
            public void run() {
                System.out.println("Thread run...");
                System.out.println("Thread end.");
            }
        };
        t.start();
        System.out.println("Main end...");
    }
}

Here, the main thread (indicated in blue) executes four lines of code:

  1. Prints "Main start..."
  2. Creates a Thread object
  3. Calls start() to launch the new thread
  4. Prints "Main end..."

When the start() method is called, the JVM creates a new thread represented by the instance t and begins its execution concurrently. Meanwhile, the main thread continues to execute and prints "Main end...". The new thread t concurrently executes and prints "Thread run..." and "Thread end."

When the run() method completes, the new thread terminates. Similarly, when the main() method finishes, the main thread terminates.

Execution Order of Threads

Consider the following execution sequence:

  1. The main thread always prints "Main start..." first.
  2. It then prints "Main end..." but the order between "Main end..." and the thread's "Thread run..." and "Thread end." messages is not guaranteed. This is because once the new thread starts running, both the main thread and the new thread execute concurrently, and their exact scheduling is determined by the operating system.

Simulating Concurrent Execution with Thread.sleep()

To simulate the effect of concurrent execution, we can use Thread.sleep() within the threads to force them to pause for a certain period:

java
// Multithreading
public class Main {
    public static void main(String[] args) {
        System.out.println("Main start...");
        Thread t = new Thread() {
            public void run() {
                System.out.println("Thread run...");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {}
                System.out.println("Thread end.");
            }
        };
        t.start();
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {}
        System.out.println("Main end...");
    }
}

The sleep() method takes a parameter in milliseconds. By adjusting the sleep duration, we can observe different execution orders between the main thread and the new thread.

Important Note: Directly calling the run() method of a Thread instance is ineffective:

java
public class Main {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.run();
    }
}

class MyThread extends Thread {
    public void run() {
        System.out.println("Hello");
    }
}

Calling the run() method directly is equivalent to invoking a regular Java method. The current thread (main thread) remains unchanged, and no new thread is created. The above code simply calls the run() method within the main() thread, printing "Hello" without creating any new threads.

Must Call start(): To actually start a new thread, you must call the start() method on the Thread instance. If you examine the Thread class source code, you'll find that the start() method internally invokes a private native method start0(). The native modifier indicates that this method is implemented in the JVM’s internal C code, not in Java.

Thread Priority

Threads can be assigned priorities using the following method:

java
Thread.setPriority(int n) // 1~10, default value is 5

The JVM automatically maps priorities from 1 (low) to 10 (high) to the actual operating system priorities (different operating systems have varying priority ranges). Higher-priority threads are scheduled more frequently by the operating system, but you cannot rely on priority settings to ensure that high-priority threads will always execute first.

Exercise

Create a new thread.

Summary

  • Thread Representation: Java uses Thread objects to represent threads. Calling start() on a Thread instance launches a new thread.
  • Single start() Call: A thread object can only have its start() method called once.
  • Execution Code: The code executed by a thread is written inside the run() method.
  • Thread Scheduling: Thread scheduling is determined by the operating system, and the program itself cannot dictate the scheduling order.
  • Pausing Threads: Thread.sleep() can pause the current thread for a specified duration.
Creating New Threads has loaded