Java 如何拦截线程生命周期?
创建线程时可以记录日志。我们需要有一个自定义的Java 如何拦截线程生命周期?,java,multithreading,lifecycle,Java,Multithreading,Lifecycle,创建线程时可以记录日志。我们需要有一个自定义的ThreadFactory实现,所有线程都将从这里创建,我们可以通过newThread方法记录它。但是,如果我们需要在线程被销毁和删除时记录日志,我们怎么做呢 import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; public enum MyThread
ThreadFactory
实现,所有线程都将从这里创建,我们可以通过newThread
方法记录它。但是,如果我们需要在线程被销毁和删除时记录日志,我们怎么做呢
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;
}
}
由于您已经实现了自己的线程工厂,一种方法是将您的runnable包装到另一个runnable中,在作业启动和完成时记录该runnable。像这样:
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);
// ...
}
这不会记录实际的线程生命周期,但与信任终结器在线程被销毁时记录相比,它是可靠的
用您选择的日志调用替换
System.out.println
。您可以在Runnable
上创建一个代理,并使用proxiedRunnable
创建一个线程,这样您就可以控制run方法何时开始和结束
public enum RpiThreadFactory {
INSTANCE;
private final AtomicInteger poolNumber = new AtomicInteger(1);
private final Logger logger = Logger.getLogger(this.name());
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) {
Runnable proxyRunnable = (Runnable) Proxy.newProxyInstance(runnable.getClass().getClassLoader(), runnable.getClass().getInterfaces(),
new RunnableProxy(runnable));
Thread thread = new Thread(threadGroup, proxyRunnable, namePrefix + threadNumber.getAndIncrement(), 0);
thread.setPriority(Thread.NORM_PRIORITY);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable cause) {
logger.fine(cause.getMessage());
}
});
logger.fine(thread.toString() + " created.");
return thread;
}
}
class RunnableProxy implements InvocationHandler {
private Runnable runnable;
public RunnableProxy(Runnable runnable) {
this.runnable = runnable;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxied Runnable Started!!");
Object object = method.invoke(runnable, args);
System.out.println("Proxied Runnable Done!!");
return object;
}
}
您正在尝试使用自己的线程池吗?是否存在需要管理自己的线程池的有效案例?您所说的“当线程被删除时”是什么意思?从何处/何处删除?您可以返回而不是返回
WorkerThread extends Thread
,该线程在完成时有一个对MyThreadFactory
的回调,您可能还应该重新抛出。并使用真正的日志库而不是System.out.println进行日志记录。@llogiq real logging library是的,但我喜欢在回答中避免附加依赖项。我不同意重新抛出,如果一个异常实际上是从run方法抛出的,那么它将在线程的异常处理程序中结束。我更喜欢明确地处理它。但是应该记录它。关于日志记录,可以,但您至少应该正确处理InterruptedException,请参阅@llogiq我在这段代码中没有阻塞操作。我看不出处理InterruptedException
有什么关系。请详细说明。@llogiq此外,Runnable.run()
不能抛出InterruptedException
。这是一个选中的异常。