Java Thread Class
The Thread class is a core class in Java for creating and managing threads.
In Java, every thread is an instance of the Thread class. A thread can be understood as an independently executing "subtask" in a program, allowing the program to perform multiple operations simultaneously.
There are two ways to create threads in Java:
- Extend the Thread class
- Implement the Runnable interface
Basic Usage of Thread Class
Creating Threads
Example
// Method 1: Extend the Thread class
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
}
// Method 2: Implement the Runnable interface
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
// Using the inheritance approach
MyThread thread1 = new MyThread();
thread1.start();
// Using the interface approach
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
}
}
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
}
// Method 2: Implement the Runnable interface
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
// Using the inheritance approach
MyThread thread1 = new MyThread();
thread1.start();
// Using the interface approach
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
}
}
Thread Lifecycle
Java threads have the following states:
- NEW: Newly created thread, the start() method has not been called yet
- RUNNABLE: Runnable state, may be running or waiting for CPU time
- BLOCKED: Thread is blocked, waiting to acquire the monitor lock
- WAITING: Waiting state, waiting for other threads to perform specific operations
- TIMED_WAITING: Timed waiting state
- TERMINATED: Thread has terminated
Common Methods of Thread Class
Basic Control Methods
Example
Thread thread = new Thread(() -> {
System.out.println("Thread executing");
});
thread.start(); // Start the thread
thread.join(); // Wait for the thread to finish
thread.sleep(1000); // Thread sleeps for 1 second
System.out.println("Thread executing");
});
thread.start(); // Start the thread
thread.join(); // Wait for the thread to finish
thread.sleep(1000); // Thread sleeps for 1 second
Thread Priority
Example
thread.setPriority(Thread.MAX_PRIORITY); // Highest priority (10)
thread.setPriority(Thread.NORM_PRIORITY); // Default priority (5)
thread.setPriority(Thread.MIN_PRIORITY); // Lowest priority (1)
thread.setPriority(Thread.NORM_PRIORITY); // Default priority (5)
thread.setPriority(Thread.MIN_PRIORITY); // Lowest priority (1)
Thread Interruption
Example
thread.interrupt(); // Interrupt the thread
// Check interrupt status in the thread
if (Thread.interrupted()) {
// Handle interrupt logic
}
// Check interrupt status in the thread
if (Thread.interrupted()) {
// Handle interrupt logic
}
Thread Synchronization
When multiple threads access shared resources, synchronization mechanisms must be used to avoid data inconsistency issues.
Using the synchronized Keyword
Example
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
private int count = 0;
public synchronized void increment() {
count++;
}
}
Using the Lock Interface
Example
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
Thread Pool and Thread Class
In actual development, thread pools are usually used to manage threads rather than directly creating Thread objects.
Example
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println("Thread executing task");
});
}
executor.shutdown();
}
}
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println("Thread executing task");
});
}
executor.shutdown();
}
}
Best Practices
- Prefer creating threads by implementing the Runnable interface
- Use thread pools to manage thread resources
- Avoid excessive synchronization; only use synchronization mechanisms when necessary
- Use the volatile keyword to ensure variable visibility
- Consider using the advanced utility classes in the Java concurrency package (java.util.concurrent)
By making reasonable use of the Thread class and related concurrency tools, you can write efficient and reliable multi-threaded Java programs.
More Extensions