
Java Threads in Java
In Java, threads are lightweight sub-processes that allow for concurrent execution of tasks within a program. A thread is the smallest unit of execution in a Java program. Using threads, Java programs can perform multiple operations simultaneously, which is useful for tasks such as handling user input, performing computations, or managing multiple network connections.
Thread Basics in Java
In Java, there are two main ways to create threads:
By extending the
Thread
class.By implementing the
Runnable
interface.
1. Using the Thread
Class
The simplest way to create a thread in Java is to extend the Thread
class and override its run()
method. The run()
method contains the code to be executed by the thread.
Syntax:
class MyThread extends Thread { public void run() { // Code to be executed by the thread System.out.println("Thread is running"); }}public class ThreadExample { public static void main(String[] args) { // Create an instance of MyThread MyThread thread = new MyThread(); // Start the thread thread.start(); // The run() method is invoked when start() is called }}
start()
: Thestart()
method is used to begin the thread’s execution. It internally calls therun()
method.run()
: This method contains the code that is executed when the thread starts.
2. Using the Runnable
Interface
Another way to create a thread is by implementing the Runnable
interface. This is considered a better practice when you want to implement multiple interfaces because Java supports only single inheritance.
Syntax:
class MyRunnable implements Runnable { public void run() { // Code to be executed by the thread System.out.println("Thread is running using Runnable"); }}public class ThreadExample { public static void main(String[] args) { // Create an instance of MyRunnable MyRunnable myRunnable = new MyRunnable(); // Create a thread object and pass the Runnable instance to it Thread thread = new Thread(myRunnable); // Start the thread thread.start(); }}
In this approach:
run()
: The method defined in theRunnable
interface contains the code that will be executed by the thread.Thread
: A newThread
object is created by passing theRunnable
object to its constructor, and thenstart()
is invoked.
Thread Lifecycle
A thread goes through several states in its lifecycle:
New: A thread is in the "new" state when it is created but has not yet started.
Runnable: After calling
start()
, a thread is considered to be in the "runnable" state, meaning it is eligible for running, though it may not be running immediately.Blocked: A thread enters the "blocked" state when it is waiting for a resource that another thread holds (for example, waiting to acquire a lock).
Waiting: A thread enters the "waiting" state when it waits indefinitely for another thread to perform a specific action.
Timed Waiting: A thread is in this state when it is waiting for a specific period (e.g.,
Thread.sleep()
).Terminated: A thread is in the "terminated" state when it has completed its task or has been stopped.
Thread Methods
Here are some commonly used methods in the Thread
class:
start()
: Starts the thread and invokes therun()
method.run()
: Contains the code to be executed by the thread.sleep(long millis)
: Causes the thread to pause for the specified number of milliseconds.join()
: Makes the current thread wait until the thread on which it is called finishes execution.getName()
: Returns the name of the thread.setName(String name)
: Sets the name of the thread.getState()
: Returns the state of the thread.
Example: Thread Sleep and Join
class MyThread extends Thread { public void run() { try { // Simulate some work by sleeping for 2 seconds System.out.println("Thread is working..."); Thread.sleep(2000); System.out.println("Thread finished work"); } catch (InterruptedException e) { System.out.println("Thread interrupted"); } }}public class ThreadExample { public static void main(String[] args) { MyThread thread1 = new MyThread(); thread1.start(); // Start thread1 try { // Wait for thread1 to finish before continuing thread1.join(); System.out.println("Thread1 has completed. Main thread proceeding..."); } catch (InterruptedException e) { System.out.println("Main thread interrupted"); } }}
Output:
Thread is working...Thread finished workThread1 has completed. Main thread proceeding...
Synchronization in Java
When multiple threads access shared resources, it can lead to issues like data inconsistency. To prevent this, you can use synchronization to ensure that only one thread can access the shared resource at a time.
Synchronized Method:
class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; }}public class ThreadExample { public static void main(String[] args) throws InterruptedException { Counter counter = new Counter(); // Create two threads that modify the counter Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }); // Start both threads t1.start(); t2.start(); // Wait for both threads to finish t1.join(); t2.join(); // Print the final count System.out.println("Final count: " + counter.getCount()); }}
In this example:
synchronized
ensures that the increment method is thread-safe. Only one thread can access theincrement()
method at a time.
Thread Pools in Java
Instead of creating and managing individual threads, Java provides Thread Pools using the Executor
framework. This is a more efficient way to manage a large number of threads.
import java.util.concurrent.*;public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { executor.submit(() -> { System.out.println(Thread.currentThread().getName() + " is running"); }); } // Shutdown the executor executor.shutdown(); }}
Key Points to Remember:
Threads enable concurrent execution and allow a program to perform multiple tasks simultaneously.
Threads can be created by extending the
Thread
class or implementing theRunnable
interface.The
run()
method contains the logic executed by the thread.Threads can be synchronized to prevent race conditions when accessing shared resources.
The
ExecutorService
provides a better way to manage a pool of threads for large applications.
Let me know if you'd like more details on a specific thread concept or need further examples!