Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to intercept Thread lifecycle?

It is possible to log when a thread is created. We need to have a custom ThreadFactory implementation from where all the threads will be created and from the newThread method we can log it. But if we need to log when the thread is destroyed and removed how can we do that?

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.log4j.Logger;

public enum MyThreadFactory implements ThreadFactory {
    INSTANCE;

    private final AtomicInteger poolNumber = new AtomicInteger(1);
    private final Logger logger = Logger.getLogger(getClass());
    private final ThreadGroup threadGroup;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    private RpiThreadFactory() {
        SecurityManager securityManager = System.getSecurityManager();
        threadGroup = (securityManager != null) ? securityManager.getThreadGroup() : Thread.currentThread().getThreadGroup();
        namePrefix = "RpiPool-" + poolNumber.getAndIncrement() + "-Thread-";

    }

    public Thread newThread(Runnable runnable) {
        Thread thread = new Thread(threadGroup, runnable, namePrefix + threadNumber.getAndIncrement(), 0);
        thread.setPriority(Thread.NORM_PRIORITY);
        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

            public void uncaughtException(Thread thread, Throwable cause) {
                logger.error(cause.getMessage(), cause);
            }
        });

        logger.debug(thread.toString() + " created.");
        return thread;
    }
}
like image 398
Tapas Bose Avatar asked Oct 18 '25 04:10

Tapas Bose


1 Answers

Since you are already implementing your own thread factory, one way would be to wrap your runnable into another runnable that logs when the job is started and completed. Like this:

 public Thread newThread(Runnable runnable) {
     Runnable wrapper = new Runnable() {

        @Override
        public void run() {
            System.out.println("Starting thread ...");
            try {
                runnable.run();
                System.out.println("Thread done");
            } catch (Throwable t) {
                System.out.println("Thread exited abnormally");
                // Log exception
            }

        }

     };
     Thread thread = new Thread(threadGroup, wrapper, namePrefix + threadNumber.getAndIncrement(), 0);
    // ...
}

This does not log the actual thread lifecycle but it is reliable compared to for example trusting a finalizer to log when a thread is destroyed.

Replace System.out.println with logging calls of your choice.

like image 63
K Erlandsson Avatar answered Oct 19 '25 17:10

K Erlandsson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!