NPE 在 java 中尝试创建多个记录器时使用静态 ThreadLocal 记录器
NPE using static ThreadLocal logger while trying to create multiple loggers in java
我正在尝试使用 Threadlocal 创建多个静态记录器,以便每个静态 threadlocal 然后将记录到具有不同消息的单独文件。下面是我的示例代码:
public class LoggerTest implements Runnable
{
private static ThreadLocal<Logger> log=new ThreadLocal<Logger>();
FileHandler fh;
String str;
public LoggerTest(int counter,String instanceName) throws SecurityException, IOException
{
str=instanceName;
log.set(Logger.getLogger("Logging"+counter));
log.get().info("m");
fh=new FileHandler(instanceName+".log");
fh.setFormatter(new SimpleFormatter());
log.get().addHandler(fh);
}
public static void main(String[] args) throws SecurityException, IOException
{
Thread t1=new Thread(new LoggerTest(1, "file"+1),"Thread1");
Thread t2=new Thread(new LoggerTest(2, "file"+2),"Thread2");
Thread t3=new Thread(new LoggerTest(3, "file"+3),"Thread3");
t1.start();t2.start();t3.start();
}
@Override
public void run()
{
for (int i = 0; i < 10; i++)
{
log.get().info("Message"+i);
try
{
Thread.sleep(5000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
根据this,每个线程都有自己的静态 ThreadLocal 变量。所以我创建了 3 个线程来使用 ThreadLocal 登录不同的文件。有人能指出我在理解静态 ThreadLocal 的概念时哪里出错了吗
我的objective:
使用静态 ThreadLocal 实现多个记录器
TIA!!!
这是因为您需要为 ThreadLocal
class 覆盖 initialValue()
方法。例如。
/** Thread local logger. */
private static final ThreadLocal<Logger> LOGGER = new ThreadLocal<Logger> () {
@Override
protected Logger initialValue() {
return LoggerFactory.getLogger(ThisClass.class);
}
};
如果您希望该字段在每个实例中都是唯一的,请不要使用静态变量!
public class LoggerTest implements Runnable
{
private final Logger log;
(...)
public LoggerTest(int counter, String instanceName) throws SecurityException, IOException
{
log = Logger.getLogger("Logging " + counter);
fh = new FileHandler(instanceName + ".log");
fh.setFormatter(new SimpleFormatter());
log.addHandler(fh);
}
(...)
@Override
public void run()
{
(...)
log.info("Message" + i);
}
}
相反,您还可以检查 log4j 框架功能:
http://logging.apache.org/log4j/1.2/manual.html
How to create different log files for different packages using same log4j logger?
Log4J loggers for different classes
log4j: Log output of a specific class to a specific appender
我发现我哪里出错了。以下是解决方案。
public class LoggerTest implements Runnable
{
static int inc=0;
private static ThreadLocal<Logger> log=new ThreadLocal<Logger>();
FileHandler fh;
int str;
public LoggerTest(int counter,String instanceName) throws SecurityException, IOException
{
str=counter;
fh=new FileHandler(instanceName+".log");
fh.setFormatter(new SimpleFormatter());
}
public static void main(String[] args) throws SecurityException, IOException
{
Thread t1=new Thread(new LoggerTest(1, "file"+1),"Thread1");
Thread t2=new Thread(new LoggerTest(2, "file"+2),"Thread2");
Thread t3=new Thread(new LoggerTest(3, "file"+3),"Thread3");
Thread t4=new Thread(new LoggerTest(4, "file"+4),"Thread4");
t1.start();t2.start();t3.start();t4.start();
}
void meth()
{
log.set(Logger.getLogger("Logging"+str));
log.get().addHandler(fh);
for (int i = 0; i < 5; i++)
{
log.get().info(log.get().getName()+" Message"+i+" "+RandomStringUtils.random(str));
try
{
Thread.sleep(5000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
@Override
public void run()
{
this.meth();
}
}
原因是我试图在构造函数中设置 ThreadLocal。主线程初始化日志一次,然后它被 null 覆盖。因此,当我们触发 Thread.start() 时,就会创建实际的线程。我们必须在线程启动后设置 ThreadLocal。希望对您有所帮助。
我正在尝试使用 Threadlocal 创建多个静态记录器,以便每个静态 threadlocal 然后将记录到具有不同消息的单独文件。下面是我的示例代码:
public class LoggerTest implements Runnable
{
private static ThreadLocal<Logger> log=new ThreadLocal<Logger>();
FileHandler fh;
String str;
public LoggerTest(int counter,String instanceName) throws SecurityException, IOException
{
str=instanceName;
log.set(Logger.getLogger("Logging"+counter));
log.get().info("m");
fh=new FileHandler(instanceName+".log");
fh.setFormatter(new SimpleFormatter());
log.get().addHandler(fh);
}
public static void main(String[] args) throws SecurityException, IOException
{
Thread t1=new Thread(new LoggerTest(1, "file"+1),"Thread1");
Thread t2=new Thread(new LoggerTest(2, "file"+2),"Thread2");
Thread t3=new Thread(new LoggerTest(3, "file"+3),"Thread3");
t1.start();t2.start();t3.start();
}
@Override
public void run()
{
for (int i = 0; i < 10; i++)
{
log.get().info("Message"+i);
try
{
Thread.sleep(5000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
根据this,每个线程都有自己的静态 ThreadLocal 变量。所以我创建了 3 个线程来使用 ThreadLocal 登录不同的文件。有人能指出我在理解静态 ThreadLocal 的概念时哪里出错了吗
我的objective: 使用静态 ThreadLocal 实现多个记录器 TIA!!!
这是因为您需要为 ThreadLocal
class 覆盖 initialValue()
方法。例如。
/** Thread local logger. */
private static final ThreadLocal<Logger> LOGGER = new ThreadLocal<Logger> () {
@Override
protected Logger initialValue() {
return LoggerFactory.getLogger(ThisClass.class);
}
};
如果您希望该字段在每个实例中都是唯一的,请不要使用静态变量!
public class LoggerTest implements Runnable
{
private final Logger log;
(...)
public LoggerTest(int counter, String instanceName) throws SecurityException, IOException
{
log = Logger.getLogger("Logging " + counter);
fh = new FileHandler(instanceName + ".log");
fh.setFormatter(new SimpleFormatter());
log.addHandler(fh);
}
(...)
@Override
public void run()
{
(...)
log.info("Message" + i);
}
}
相反,您还可以检查 log4j 框架功能:
http://logging.apache.org/log4j/1.2/manual.html
How to create different log files for different packages using same log4j logger?
Log4J loggers for different classes
log4j: Log output of a specific class to a specific appender
我发现我哪里出错了。以下是解决方案。
public class LoggerTest implements Runnable
{
static int inc=0;
private static ThreadLocal<Logger> log=new ThreadLocal<Logger>();
FileHandler fh;
int str;
public LoggerTest(int counter,String instanceName) throws SecurityException, IOException
{
str=counter;
fh=new FileHandler(instanceName+".log");
fh.setFormatter(new SimpleFormatter());
}
public static void main(String[] args) throws SecurityException, IOException
{
Thread t1=new Thread(new LoggerTest(1, "file"+1),"Thread1");
Thread t2=new Thread(new LoggerTest(2, "file"+2),"Thread2");
Thread t3=new Thread(new LoggerTest(3, "file"+3),"Thread3");
Thread t4=new Thread(new LoggerTest(4, "file"+4),"Thread4");
t1.start();t2.start();t3.start();t4.start();
}
void meth()
{
log.set(Logger.getLogger("Logging"+str));
log.get().addHandler(fh);
for (int i = 0; i < 5; i++)
{
log.get().info(log.get().getName()+" Message"+i+" "+RandomStringUtils.random(str));
try
{
Thread.sleep(5000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
@Override
public void run()
{
this.meth();
}
}
原因是我试图在构造函数中设置 ThreadLocal。主线程初始化日志一次,然后它被 null 覆盖。因此,当我们触发 Thread.start() 时,就会创建实际的线程。我们必须在线程启动后设置 ThreadLocal。希望对您有所帮助。