riven

Riven

Riven

Creating threads in java with example

A thread is a lightweight subprocess, the smallest unit of processing that can be scheduled by an operating system. In Java, threads allow concurrent execution of code, improving application performance and responsiveness. Each thread has its own execution context, which includes its own call stack and local variables, while sharing memory space with other threads.

Benefits of Using Threads

  1. Concurrency: Threads enable multiple operations to run concurrently, improving application throughput.
  2. Responsiveness: In graphical user interface (GUI) applications, threads prevent the application from becoming unresponsive during long-running operations.
  3. Resource Sharing: Threads can share data and resources, making inter-thread communication easier.

The Thread Lifecycle

A thread in Java undergoes several states during its lifecycle:

  1. New: The thread is created but not yet started.
  2. Runnable: The thread is ready to run and waiting for CPU time.
  3. Blocked: The thread is blocked and waiting to acquire a monitor lock.
  4. Waiting: The thread is waiting indefinitely for another thread to perform a specific action (like notify()).
  5. Timed Waiting: The thread is waiting for another thread to perform an action for a specified time.
  6. Terminated: The thread has completed its execution.

Thread State Diagram

Creating Threads in Java

There are two primary ways to create threads in Java:

  1. Extending the Thread class: By creating a subclass of the Thread class and overriding its run() method.
  2. Implementing the Runnable interface: By creating a class that implements the Runnable interface and defining the run() method.

Method 1: Extending the Thread Class

To create a thread by extending the Thread class, follow these steps:

  1. Create a subclass of Thread.
  2. Override the run() method to define the code that will be executed by the thread.
  3. Create an instance of the subclass and call the start() method to initiate the thread.

Example of Extending Thread Class

				
					class MyThread extends Thread {
    @Override
    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) {
                System.out.println(Thread.currentThread().getName() + " was interrupted.");
            }
        }
    }
}

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
    }
}
				
			

Explanation of the Example

  1. Subclassing Thread: The MyThread class extends the Thread class and overrides the run() method, which contains the code to be executed by the thread.
  2. Thread Execution: The start() method is called on each thread instance. This method invokes the run() method in a new call stack.
  3. Sleeping: Each thread prints its name and a count, then sleeps for 500 milliseconds to simulate work.

Method 2: Implementing the Runnable Interface

The second approach to creating threads in Java is by implementing the Runnable interface. This is often preferred because it allows for better separation of concerns and can be used with thread pools and other concurrency utilities.

Steps to Implement Runnable Interface

  1. Create a class that implements the Runnable interface.
  2. Override the run() method to define the code that will be executed by the thread.
  3. Create a Thread object by passing an instance of the Runnable class to the Thread constructor.
  4. Call the start() method on the Thread object.

Example of Implementing Runnable Interface

				
					class MyRunnable implements Runnable {
    @Override
    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) {
                System.out.println(Thread.currentThread().getName() + " was interrupted.");
            }
        }
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread(myRunnable);
        Thread thread2 = new Thread(myRunnable);

        thread1.start(); // Start thread1
        thread2.start(); // Start thread2
    }
}
				
			

Explanation of the Runnable Example

  1. Implementing Runnable: The MyRunnable class implements the Runnable interface and overrides the run() method.
  2. Thread Creation: Two Thread objects are created, each taking the same MyRunnable instance.
  3. Starting Threads: The start() method is called on both thread instances, executing the run() method concurrently.

Thread Methods

Java provides several methods in the Thread class for managing threads. Some commonly used methods include:

  • start(): Starts the execution of the thread.
  • run(): Contains the code to be executed by the thread.
  • sleep(long millis): Pauses the current thread for a specified time.
  • join(): Waits for the thread to finish execution before proceeding.
  • interrupt(): Interrupts a thread, setting its interrupt flag.
  • isAlive(): Checks if the thread is still running.

Example of Using Thread Methods

				
					class CounterThread extends Thread {
    private int count = 0;

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

    public int getCount() {
        return count;
    }
}

public class ThreadMethodExample {
    public static void main(String[] args) {
        CounterThread thread1 = new CounterThread();
        CounterThread thread2 = new CounterThread();

        thread1.start(); // Start thread1
        thread2.start(); // Start thread2

        try {
            thread1.join(); // Wait for thread1 to finish
            thread2.join(); // Wait for thread2 to finish
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Both threads have finished execution.");
    }
}
				
			

Explanation of the Thread Method Example

  1. CounterThread Class: The CounterThread class extends Thread and maintains a count variable.
  2. Run Method: The run() method increments the count and prints its value, then sleeps for 500 milliseconds.
  3. Join Method: The join() method is used to ensure that the main thread waits for both CounterThread instances to finish before printing the final message.

Thread Synchronization

When multiple threads access shared resources, synchronization is necessary to avoid data inconsistency and race conditions. Java provides synchronization mechanisms to control the access of multiple threads to shared resources.

Synchronized Methods

A synchronized method allows only one thread to execute it at a time, ensuring that shared resources are accessed in a thread-safe manner.

Example of Synchronized Method

				
					class SynchronizedCounter {
    private int count = 0;

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

    public int getCount() {
        return count;
    }
}

public class SynchronizedMethodExample {
    public static void main(String[] args) {
        SynchronizedCounter counter = new SynchronizedCounter();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };

        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + counter.getCount());
    }
}
				
			

Explanation of Synchronized Method Example

  1. SynchronizedCounter Class: The SynchronizedCounter class has a synchronized method increment() that safely increments the count.
  2. Thread Execution: Two threads are created to increment the counter concurrently.
  3. Final Count: The main thread waits for both threads to finish and prints the final count, ensuring accurate results due to synchronization.

Synchronized Blocks

Synchronized blocks provide finer control over synchronization by allowing only specific sections of code to be synchronized.

Example of Synchronized Block

				
					class SynchronizedBlockCounter {
    private int count = 0;

    public void increment() {
        synchronized (this) { // Synchronized block
            count++;
        }
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizedBlockExample {
    public static void main(String[] args) {
        SynchronizedBlockCounter counter = new SynchronizedBlockCounter();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        };

        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + counter.getCount());
    }
}
				
			

Explanation of Synchronized Block Example

  1. Synchronized Block: The increment() method contains a synchronized block that ensures only one thread can increment the count at a time.
  2. Concurrent Execution: The example runs two threads incrementing the counter, demonstrating thread safety using synchronized blocks.

Related topic

Vector in java
Vector in java with example In Java, the Vector class is part of the Java Collections Framework and represents...
Java Memory Management
Java Memory Management Java Memory Management is an essential aspect of Java programming that involves...
Creating threads in java
Creating threads in java with example A thread is a lightweight subprocess, the smallest unit of processing...
Java while loop with example
Java while loop with example The while loop is a fundamental control structure in Java that allows developers...
Java operators with example
Java operators with example Operators are special symbols that perform operations on variables and values....
Java generics
What Are Java Generics? Java Generics are a powerful feature introduced in Java 5 that allows you to...
Java checked exception
java Checked Exceptions Java’s exception handling framework is a powerful feature that helps developers...
AWT panel in java
What is AWT Panel in Java? A Panel in Java refers to an instance of the JPanel class, which is part of...
Swing in java
Swing in java with example Java Swing is a part of Java Foundation Classes (JFC) that provides a rich...
Break statement in java
Break statement in java The break statement in Java is a control flow statement that allows you to terminate...