Most executors can be constructed with a ThreadFactory. That's also true for ForkJoinPool. However, for simplification, I use a different ExecutorService.
ExecutorService executor = Executors.newFixedThreadPool(
10, new FinalizerThreadFactory(Executors.defaultThreadFactory()));
The class FinalizerThreadFactory delegates the creation of threads to the passed thread factory. However, it creates threads that will execution some additional code before they exit. That's quite simple:
class FinalizerThreadFactory implements ThreadFactory {
private final ThreadFactory delegate;
public FinalizerThreadFactory(ThreadFactory delegate) {
this.delegate = delegate;
}
public Thread newThread(final Runnable r) {
return delegate.newThread(new Runnable() {
public void run() {
try {
r.run();
} finally {
// finalizer code goes here.
}
}
});
}
}