1

Context: I want to add a log Handler to the root logger in order to collect all logging output from a task. During task execution, other threads might get created. I want their log output, too.

Some of those threads are created by methods of libraries, like Ant for example.

Currently my log handler checks the current Thread in the publish method, and stores the record if it is the same as the original task thread. But I miss the log messages of the threads spawned by the task thread.

Just going by start/stop time doesn't work either because multiple tasks are running concurrently, each with their own potential child-threads.

Reto Höhener
  • 5,419
  • 4
  • 39
  • 79
  • You could always extend the `Thread` class and require a parent thread in the constructor, then use a getter. – Cardinal System Dec 28 '17 at 19:54
  • 1
    Unfortunately I have no control over thread creation that happens in the used libraries. – Reto Höhener Dec 28 '17 at 19:55
  • Does it? I have to check if my eclipse does this as well. – Reto Höhener Dec 28 '17 at 19:58
  • 1
    If you have control of the initial thread, you can create it in a new `ThreadGroup`, since most threads by default are created in the same group as their "parent" thread, and then use the `ThreadGroup` for you logging filter. However, this won't work if a library creates a thread in a specific thread group, and it won't work if a library uses a thread pool, so you might be out of luck. – Andreas Dec 28 '17 at 19:59
  • @CardinalSystem looks like my eclipse shows just a flat list of threads in the debugger. – Reto Höhener Dec 28 '17 at 20:00
  • @Andreas that's interesting, and would already be a nice improvement over the current situation. I will try that immediately. – Reto Höhener Dec 28 '17 at 20:01
  • @CardinalSystem I don't know what that means. It's a web application running inside tomcat. At application/server startup I start a scheduler thread, which in turn starts a nightly backup task for each of several subsystems. – Reto Höhener Dec 28 '17 at 20:54

1 Answers1

1

Every thread instance has a ThreadGroup within it. The thread groups form a tree in which every thread group except the initial thread group has a parent. Using this information, we can apply the ThreadGroup#parentOf(ThreadGroup) method to check if the current thread is the parent of the given thread:

// potentialParent would probably just be Thread.currentThread();
public static boolean isChild(Thread potentialChild, Thread potentialParent) {
    try {
        return potentialParent.getThreadGroup().parentOf(potentialChild.getThreadGroup());
    }catch(NullPointerException e) {
        e.printStackTrace();            
    }
    return false;
}

Some IDEs will show every running thread if you use the debugger. Take Eclipse's Debug View for example. Each thread in your program appears as a node in the tree:

Debug View

If you want to take a step further and do some dirty work, you could use reflection to access the threads stored in given thread group, but I dissuade you from taking such measures:

// There is a thread array field in the ThreadGroup class.
Field f = ThreadGroup.class.getDeclaredField("threads");
// The 'threads' field has no access modifiers.
f.setAccessible(true);

Thread[] threads = (Thread[]) f.get(Thread.currentThread().getThreadGroup());
/*
 * Search 'threads' accordingly...
 */

You can also play around a bit with ThreadUtils.getAllThreadGroups() if you happen to have Appache commons lang on your build path.

Cardinal System
  • 2,749
  • 3
  • 21
  • 42
  • Thank you, sounds fantastic. I am implementing and testing this right now. Also, which IDE do you use that shows the thread hierarchy? – Reto Höhener Dec 28 '17 at 21:04
  • Looks like it's working :). I am also setting a custom ThreadGroup for my backup tasks now. Thanks again. – Reto Höhener Dec 28 '17 at 21:26
  • @RetoHöhener I didn't see your second comment until now (2yrs later). Happy things are working out for you. If you are interested in learning a little more, take a look at [this similar question](https://stackoverflow.com/a/3018672/5645656). – Cardinal System Dec 22 '19 at 05:40