Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Multithreading in Java: Core Methods and Thread Pool Configuration

Tech 3

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

  1. Extending the Thread class
  2. Implementing the Runnable interface
  3. Implementing the Callable interface with ExecutorService and Future
  4. Utilizing an ExecutorService thread 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 reaching maximumPoolSize, 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 to corePoolSize. If allowCoreThreadTimeOut is enabled, core threads may also be subject to timeout.
  • unit: The time unit for keepAliveTime, such as TimeUnit.SECONDS.
  • workQueue: The task queue. This blocking queue holds tasks awaiting execution. Once corePoolSize is 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 maximumPoolSize and the queue is full). Common policies include:
    1. AbortPolicy: Throws a RejectedExecutionException.
    2. CallerRunsPolicy: Executes the task in the caller's thread.
    3. DiscardPolicy: Silently dsicards the task.
    4. DiscardOldestPolicy: Discards the oldest unhandled task from the queue and retries execution of the new task.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.