How to use MDC with thread pools in Java?

Better Stack Team
Updated on August 25, 2023

In Java, MDC (Mapped Diagnostic Context) is a feature provided by logging frameworks like Log4j and Logback. It allows you to associate key-value pairs with the current thread's execution context, which can be very useful in multi-threaded environments, including scenarios involving thread pools.

Using MDC with thread pools involves setting and clearing MDC values appropriately before and after executing tasks in the thread pool. This ensures that each task executed by a thread in the pool has its specific MDC values, preventing interference between threads.

Here's how you can use MDC with thread pools in Java:

1. Initialize MDC values before submitting tasks to the thread pool

Before submitting tasks to the thread pool, set the MDC values that you want to associate with the executing threads. For example:

 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class Task implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(Task.class);

    private String requestId;

    public Task(String requestId) {
        this.requestId = requestId;
    }

    @Override
    public void run() {
        // Set MDC values for the current thread
        MDC.put("requestId", requestId);

        // Perform your task logic
        LOGGER.info("Processing request: {}", requestId);

        // Clear MDC values to avoid interference with other tasks
        MDC.clear();
    }
}

2. Submit tasks to the thread pool

Once you have the tasks created with their associated MDC values, you can submit them to the thread pool for execution. Make sure to use an appropriate thread pool implementation, such as ExecutorService, to manage the threads.

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

public class Main {
    public static void main(String[] args) {
        // Create a thread pool with a fixed number of threads
        int numThreads = 5;
        ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);

        // Submit tasks with different requestId values
        for (int i = 1; i <= 10; i++) {
            String requestId = "REQ_" + i;
            threadPool.submit(new Task(requestId));
        }

        // Shutdown the thread pool when no more tasks need to be submitted
        threadPool.shutdown();
    }
}

In this example, we are creating a thread pool with five threads and submitting ten tasks, each with a different requestId. The Task class sets the requestId as an MDC value for the current thread and logs the processing of each request. After the task is completed, we clear the MDC values to prevent interference with other tasks.

By using MDC with thread pools, you can ensure that each task in the pool has its specific MDC values, providing a better context for log messages and easier debugging in multi-threaded applications.

To learn more about logging, visit Better Stack Community.

Got an article suggestion? Let us know
Explore more
Licensed under CC-BY-NC-SA

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Make your mark

Join the writer's program

Are you a developer and love writing and sharing your knowledge with the world? Join our guest writing program and get paid for writing amazing technical guides. We'll get them to the right readers that will appreciate them.

Write for us
Writer of the month
Marin Bezhanov
Marin is a software engineer and architect with a broad range of experience working...
Build on top of Better Stack

Write a script, app or project on top of Better Stack and share it with the world. Make a public repository and share it with us at our email.

community@betterstack.com

or submit a pull request and help us build better products for everyone.

See the full list of amazing projects on github