Answer
Multithreading in Java
Multithreading allows a program to run multiple threads (lightweight processes) concurrently, enabling parallel execution and better CPU utilization.
Thread Lifecycle
CODE
NEW → RUNNABLE → RUNNING → BLOCKED/WAITING → DEAD
Method 1: Extending Thread class
Java
class MyThread extends Thread {
private String threadName;
MyThread(String name) {
this.threadName = name;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + " - Count: " + i);
try { Thread.sleep(500); } catch (InterruptedException e) {}
}
}
}
// Create and start threads
MyThread t1 = new MyThread("Thread-1");
MyThread t2 = new MyThread("Thread-2");
t1.start(); // starts a new thread — calls run() in new thread
t2.start();
Method 2: Implementing Runnable (Preferred)
Java
class MyTask implements Runnable {
private String taskName;
MyTask(String name) { this.taskName = name; }
@Override
public void run() {
System.out.println(taskName + " executing on: " + Thread.currentThread().getName());
}
}
Thread t1 = new Thread(new MyTask("Login Test"));
Thread t2 = new Thread(new MyTask("Search Test"));
t1.start();
t2.start();
// With Lambda (Java 8+)
Thread t3 = new Thread(() -> System.out.println("Lambda thread"));
t3.start();
Method 3: ExecutorService (Modern, Preferred for Pools)
Java
import java.util.concurrent.*;
// Fixed thread pool — reuses 3 threads
ExecutorService executor = Executors.newFixedThreadPool(3);
// Submit tasks
executor.submit(() -> System.out.println("Task 1 running"));
executor.submit(() -> System.out.println("Task 2 running"));
executor.submit(() -> {
System.out.println("Task 3 running");
return "result";
});
executor.shutdown(); // no new tasks, finish existing
executor.awaitTermination(30, TimeUnit.SECONDS);
Thread Methods
Java
Thread t = new Thread(() -> {
System.out.println("Running: " + Thread.currentThread().getName());
});
t.setName("MyThread");
t.setPriority(Thread.MAX_PRIORITY); // 1-10, default 5
t.setDaemon(true); // daemon thread — dies when main thread dies
t.start();
t.join(); // wait for this thread to finish
t.interrupt(); // request interruption
Thread.sleep(1000); // current thread sleeps 1 second
Thread.currentThread().getName(); // get current thread name
Synchronization — Thread Safety
Java
class Counter {
private int count = 0;
// synchronized — only one thread can execute this at a time
public synchronized void increment() {
count++;
}
public int getCount() { return count; }
}
Counter counter = new 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(); });
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(counter.getCount()); // 2000 — correct with sync
In Parallel Test Execution (TestNG)
Java
// TestNG runs tests in parallel across browsers using multithreading
// ThreadLocal ensures each thread has its own WebDriver instance
ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>();
public WebDriver getDriver() {
return driverThreadLocal.get();
}
@BeforeMethod
public void setup() {
driverThreadLocal.set(new ChromeDriver());
}
@AfterMethod
public void teardown() {
getDriver().quit();
driverThreadLocal.remove();
}
