英文:
Not seeing full data in the string buffer in mutli thread logging
问题
我正在使用 ThreadLocal StringBuffer 将整个日志存储,以便在每个测试用例执行结束时将其移动到 kibana。但当我并行运行测试用例时,日志丢失了一些条目。
在将日志添加到 StringBuffer 之前,我将其写入文件,并在日志文件中看到所有条目,但在 StringBuffer 中看不到。
任何想法都非常感谢。
我尝试过 String Builder,但没有运气。尝试过使其同步,但还是没有运气。我尝试将日志条目写入文件,然后移动到字符串缓冲区,我在那里看到了所有的条目,但在字符串缓冲区中没有得到所有的条目。
public abstract class Messages {
static ThreadLocal<StringBuffer> msg;
public static void init() {
msg = new ThreadLocal<StringBuffer>() {
@Override
protected StringBuffer initialValue() {
return new StringBuffer();
}
};
}
public static void addMsg(String msg) {
msg.get().append(msg + "\r\n");
System.out.println(msg);
}
}
public class CallingClass(){
public void callingMethod(String threadName){
Messages.init();
Messages.addMsg("Hi");
Messages.addMsg("This");
Messages.addMsg("Is");
Messages.addMsg("Testing");
Messages.addMsg("For");
Messages.addMsg("Multi");
Messages.addMsg("Thread");
Messages.addMsg("UI");
Messages.addMsg(threadName + "!!");
}
}
从我的黄瓜测试中,我们从每个线程调用上述 callingMethod 方法。
我运行了 10 个并行线程,当我从所有 10 个线程的末尾打印 msg 时,结果是不同的,我看到对于某些线程,它丢失了前几个条目。
我尝试过将 addMsg 设为同步,但还是没有运气。在单线程执行中,日志是正确的,当我在 eclipse 中使用调试时,日志会像预期的那样正常显示。
英文:
I am using ThreadLocal StringBuffer for storing entire log to move it to kibana at the end of each test case execution. But when I am running cases in parallel, the log is loosing some entries.
I am writing the log into file before adding it to StringBuffer and I see all entires in the log file but not in the StringBuffer.
Any ideas are much appreciated.
I tried String Builder but no luck. Tried to make synchronized still no luck. I tried writing the log entry into file before moving into string buffer and I see all entire there but not getting all entries in string buffer
public abstract class Messages {
static ThreadLocal<StringBuffer> msg;
public static void init() {
msg = new ThreadLocal<StringBuffer>() {
@Override
protected StringBuffer initialValue() {
return new StringBuffer();
}
};
public static void addMsg(String msg) {
msg.get().append(msg + "\r\n");
System.out.println(msg);
}
}
public class CallingClass(){
public void callingMethod(String threadName){
Messages.init();
Messages.addMsg("Hi");
Messages.addMsg("This");
Messages.addMsg("Is");
Messages.addMsg("Testing");
Messages.addMsg("For");
Messages.addMsg("Multi");
Messages.addMsg("Thread");
Messages.addMsg("UI");
Messages.addMsg(threadName + "!!");
}
}
From my cucumber tests, we call the above method callingMethod from each thread.
I am running 10 parallel threads and the result is different when I print the msg at the end from all 10 threads, I see for some threads it is missing the first few entries.
I tried making addMsg synchronized but still no luck. In a single thread execution, the log is proper and also when I am using debug from eclipse, the log is coming properly as expected.
答案1
得分: 0
多个线程调用 Messages.init()
。
第一次调用 init
时,msg
的先前值为 null
,将被新的 ThreadLocal
替换。
下一次调用 init
时,先前的值将被 新的 ThreadLocal
副本 替换,有效地丢弃了先前使用/创建的所有 StringBuffer
对象。
再次调用时也是如此...
init
方法没有意义,你应该摆脱它(以及对它的所有调用),并且只需像这样定义 msg
:
static final ThreadLocal<StringBuffer> msg = new ThreadLocal<StringBuffer>() {
@Override
protected StringBuffer initialValue() {
return new StringBuffer();
}
};
ThreadLocal
的整个意义在于你只需要一个实例,以便为每个线程提供自己的 StringBuffer
。
此外,如果访问内容的所有方式都通过这些方法进行,那么不需要 StringBuffer
的同步/线程安全性,你应该改用 StringBuilder
。
英文:
Multiple threads call Messages.init()
.
The first time we call init
the previous value of null
for msg
is replaced with a new ThreadLocal
.
The next time we call init
the previous value is replaced with a new copy of ThreadLocal
, effectively discarding all previously used/created StringBuffer
objects.
And the same the next time ...
There's no point in that init
method and you should get rid of it (and all calls to it) and just define msg
like this:
static final ThreadLocal<StringBuffer> msg = new ThreadLocal<StringBuffer>() {
@Override
protected StringBuffer initialValue() {
return new StringBuffer();
}
};
The whole point of ThreadLocal
is that you only need one instance of it to give each thread their own StringBuffer
.
Also, if all access to the content is via those methods, then the synchronization/thread safety of StringBuffer
isn't needed and you should use a StringBuilder
instead.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论