How to Create Threads in Java

Creating threads in Java can transform the way you build applications. By allowing multiple processes to run simultaneously, you can achieve smoother performance and better resource management. But how do you get started with threads in Java? Let's find out.

Understanding Java Threads

Threads in Java are like separate paths of execution in a program. Think of them as various lanes on a highway, allowing multiple cars to travel simultaneously without waiting for one another. This increases the efficiency of traffic, just like threads enhance processing in a program.

  • Multitasking: Threads allow a program to perform multiple tasks at once.
  • Resource Management: They efficiently share resources and memory between tasks.

You might wonder: How do threads differ from processes? Unlike processes, which own their resources, threads share their memory space and resources, making them light and quick.

To understand more about Java threads and their role in concurrency, check out Understanding Concurrency and Multithreading.

Creating a Thread in Java

You can create a thread in Java in a couple of ways. Let's dive into the code examples to see how it's done.

Example 1: Using the Thread Class

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

public class Test {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();  // Starts the thread
    }
}

Explanation:

  • Extending the Thread class: By creating a class that extends Thread, you can define the run() method, which describes what the thread will do.
  • thread.start(): This is where the thread's execution begins, calling the run() method automatically.

Example 2: Implementing Runnable Interface

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Runnable is running!");
    }
}

public class TestRunnable {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable); 
        thread.start();  // Starts the thread
    }
}

Explanation:

  • Implementing Runnable: You implement the Runnable interface and define the run() method.
  • New Thread: You pass an instance of MyRunnable to the Thread constructor.

Example 3: Using Lambda Expressions (Java 8 and Later)

public class LambdaThread {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Lambda Thread is running!");
        });
        thread.start();
    }
}

Explanation:

  • Lambda Expression: This lets you write clearer and more concise code.
  • Functional Interface: Runnable is a functional interface, making it suitable for lambda expressions.

Example 4: Using Threads with Return Values

If you need a thread to return a result, you can't directly return through run(). Instead, use Callable and Future.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class CallableExample implements Callable<Integer> {
    public Integer call() throws Exception {
        return 123;
    }
}

public class CallableTest {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Integer> future = executor.submit(new CallableExample());
        
        Integer result = future.get();  // Waits for the result
        System.out.println("Result: " + result);
        
        executor.shutdown();
    }
}

Explanation:

  • Callable Interface: Similar to Runnable, but can return a result.
  • Future Object: Represents the result of an asynchronous computation.

Example 5: Managing Threads in a Pool

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 5; i++) {
            executor.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
            });
        }
        
        executor.shutdown();
    }
}

Explanation:

  • ExecutorService: Manages a pool of threads.
  • FixedThreadPool: Allows a fixed number of threads to be reused for executing tasks.

Conclusion

Creating threads in Java can significantly boost your application's performance. Whether you extend a thread, implement the Runnable interface, or manage a thread pool, Java provides flexible options to suit your needs. While threads enhance efficiency, they also introduce complexity. Practice with the examples to master threading.

For more insights into Java's capabilities, explore Go vs Java: Which Language Fits Your Needs and Java Adjustable: Programming with Flexibility.

Previous Post Next Post

Welcome, New Friend!

We're excited to have you here for the first time!

Enjoy your colorful journey with us!

Welcome Back!

Great to see you Again

If you like the content share to help someone

Thanks

Contact Form