Introduction to Java Threads: Creation, States, and Examples

Answered using GPT-4o-mini by Java Q&A Hub

Question:

Introduce Java Threads and give examples

Answer:

Java threads are a fundamental part of Java's concurrency model, allowing multiple threads to run concurrently within a single program. A thread is essentially a lightweight process that can execute code independently. Java provides built-in support for multithreading, enabling developers to create applications that can perform multiple tasks simultaneously, improving performance and responsiveness.

Key Concepts of Java Threads

  1. Thread Creation: In Java, threads can be created in two primary ways:

    • By extending the Thread class.
    • By implementing the Runnable interface.
  2. Thread States: A thread can be in one of several states:

    • New: The thread is created but not yet started.
    • Runnable: The thread is ready to run and waiting for CPU time.
    • Blocked: The thread is blocked waiting for a monitor lock.
    • Waiting: The thread is waiting indefinitely for another thread to perform a particular action.
    • Timed Waiting: The thread is waiting for another thread to perform an action for up to a specified waiting time.
    • Terminated: The thread has completed its execution.
  3. Synchronization: To prevent thread interference and ensure data consistency, Java provides synchronization mechanisms, such as synchronized methods and blocks.

  4. Thread Lifecycle: The lifecycle of a thread includes states like New, Runnable, Blocked, Waiting, Timed Waiting, and Terminated, which are managed by the Java Virtual Machine (JVM).

Example 1: Creating a Thread by Extending the Thread Class

class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " - Count: " + i);
            try {
                Thread.sleep(500); // Sleep for 500 milliseconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        
        thread1.start(); // Start thread1
        thread2.start(); // Start thread2
    }
}

Example 2: Creating a Thread by Implementing the Runnable Interface

class MyRunnable implements Runnable {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " - Count: " + i);
            try {
                Thread.sleep(500); // Sleep for 500 milliseconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new MyRunnable());
        Thread thread2 = new Thread(new MyRunnable());
        
        thread1.start(); // Start thread1
        thread2.start(); // Start thread2
    }
}

Example 3: Synchronization

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

class CounterThread extends Thread {
    private Counter counter;

    public CounterThread(Counter counter) {
        this.counter = counter;
    }

    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.increment();
        }
    }
}

public class SyncExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread thread1 = new CounterThread(counter);
        Thread thread2 = new CounterThread(counter);
        
        thread1.start();
        thread2.start();
        
        thread1.join(); // Wait for thread1 to finish
        thread2.join(); // Wait for thread2 to finish
        
        System.out.println("Final Count: " + counter.getCount());
    }
}

Summary

Java threads are a powerful feature that allows developers to create responsive and efficient applications. By understanding how to create and manage threads, as well as how to synchronize access to shared resources, you can build robust multithreaded applications. The examples provided illustrate basic thread creation, execution, and synchronization in Java.