Implementing Multithreading in Java: Core Methods and Thread Pool Configuration
Managing threads via a thread pool is the recommended approach in practice for more efficient resource control and performance enhancement.
Common Methods for Creating Threads in Java
- Extending the
Threadclass - Implementing the
Runnableinterface - Implementing the
Callableinterface withExecutorServiceandFuture - Utilizing an
ExecutorServicethread pool
Code examples for each method are provided below.
1. Extending the Thread Class
class CustomWorker extends Thread {
@Override
public void run() {
System.out.println("Thread is executing: " + this.getName());
}
}
public class ThreadDemo {
public static void main(String[] args) {
CustomWorker worker = new CustomWorker();
worker.start(); // Initiates the thread
}
}
2. Implementing the Runnable Interface
class TaskRunner implements Runnable {
@Override
public void run() {
System.out.println("Thread is executing: " + Thread.currentThread().getName());
}
}
public class RunnableDemo {
public static void main(String[] args) {
Thread workerThread = new Thread(new TaskRunner(), "TaskThread");
workerThread.start(); // Initiates the thread
}
}
3. Implementing the Callable Interface
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class ComputationTask implements Callable<Long> {
@Override
public Long call() throws Exception {
long sum = 0L;
for (int i = 1; i <= 10000; i++) {
sum += i;
}
return sum;
}
}
public class CallableDemo {
public static void main(String[] args) throws Exception {
ExecutorService service = Executors.newSingleThreadExecutor();
Future<Long> taskResult = service.submit(new ComputationTask());
Long finalSum = taskResult.get(); // Retrieves the computed result
System.out.println("Computation result: " + finalSum);
service.shutdown(); // Terminates the executor service
}
}
4. Using an ExecutorService Thread Pool
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class PooledTask implements Runnable {
@Override
public void run() {
System.out.println("Thread is executing: " + Thread.currentThread().getName());
}
}
public class ThreadPoolDemo {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
pool.execute(new PooledTask());
}
pool.shutdown(); // Initiates an orderly shutdown of the pool
}
}
Essential Parameters for Configuring a Thread Pool
- corePoolSize: The number of core threads. These threads are maintained in the pool even when idle. New threads are created to handle incoming tasks only when the number of active threads is below this value. Once the count reaches
corePoolSize, new tasks are either queued or handled according to the rejection policy. - maximumPoolSize: The maximum allowable number of threads. If the queue is full and the number of threads exceeds
corePoolSize, the pool can create additional threads up to this limit. Upon reachingmaximumPoolSize, the configured rejection policy is applied to new tasks. - keepAliveTime: The duration idle threads remain alive before termination. When the thread count exceeds
corePoolSize, threads idle longer than this period are terminated until the count returns tocorePoolSize. IfallowCoreThreadTimeOutis enabled, core threads may also be subject to timeout. - unit: The time unit for
keepAliveTime, such asTimeUnit.SECONDS. - workQueue: The task queue. This blocking queue holds tasks awaiting execution. Once
corePoolSizeis reached, newly submitted tasks are placed in this queue. - threadFactory: The factory responsible for creating new threads. It allows customization of thread properties like name, priority, and daemon status.
- handler: The rejection policy. This handler is invoked when the pool cannot accept a new task (i.e., the thread count is at
maximumPoolSizeand the queue is full). Common policies include:- AbortPolicy: Throws a
RejectedExecutionException. - CallerRunsPolicy: Executes the task in the caller's thread.
- DiscardPolicy: Silently dsicards the task.
- DiscardOldestPolicy: Discards the oldest unhandled task from the queue and retries execution of the new task.
- AbortPolicy: Throws a