[英]Can not figure out an exception
我正在编写简单的代码来将日志异步写入文件,但发现很难找出一个问题。
我在logNodes.removeFirst()
得到java.util.NoSuchElementException
。 如果我检查列表是否为空,这怎么会发生?
如果我非常频繁地登录,则通常会出现此问题。
如果有人能向我解释为什么会发生这种情况,我将不胜感激。
我的代码:
private static class FileLogger extends Thread {
private File logFile;
private PrintWriter logWriter;
private final LinkedList<LogNode> logNodes = new LinkedList<>();
public FileLogger(Context context) {
String dateString = (String) DateFormat.format("yyyy-MM-dd_HH:mm:ss", new Date());
File logsDir = new File(context.getCacheDir(), "logs");
if (logsDir.exists()) {
for (File file : logsDir.listFiles()) {
file.delete();
}
}
try {
logFile = new File(logsDir, dateString + ".log");
if (!logFile.exists()) {
logFile.getParentFile().mkdirs();
logFile.createNewFile();
}
logWriter = new PrintWriter(new FileOutputStream(logFile));
start();
} catch (IOException ignored) {
}
}
public void log(Date date, String tag, String msg) {
if (isAlive()) {
logNodes.addLast(new LogNode(date, tag, msg));
synchronized (this) {
this.notify();
}
}
}
@Override
public void run() {
while (true) {
if (logNodes.isEmpty()) {
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
logWriter.flush();
logWriter.close();
return;
}
} else {
LogNode node = logNodes.removeFirst();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
logWriter.println(String.format(
"%s %s.%s", dateFormat.format(node.date), node.tag, node.msg
));
logWriter.flush();
}
}
}
private class LogNode {
final Date date;
final String tag;
final String msg;
public LogNode(Date date, String tag, String msg) {
this.date = date;
this.tag = tag;
this.msg = msg;
}
}
}
您没有同步多个log
线程。
假设您有线程 1 和线程 2:
FileLogger
在调用isEmpty
时注意到了 node1,而 thread2 没有注意到它。FileLogger
可能不会注意到 node2,将抛出NoSuchElementException
。与其自己实现一个阻塞队列, BlockigQueue
尝试使用java.util.concurrent
提供的BlockigQueue
,让它为你做同步。
private static class FileLogger extends Thread {
private File logFile;
private PrintWriter logWriter;
private final BlockingQueue<LogNode> logNodes = new LinkedBlockingQueue<>();
public FileLogger(Context context) {
String dateString = (String) DateFormat.format("yyyy-MM-dd_HH:mm:ss", new Date());
File logsDir = new File(context.getCacheDir(), "logs");
if (logsDir.exists()) {
for (File file : logsDir.listFiles()) {
file.delete();
}
}
try {
logFile = new File(logsDir, dateString + ".log");
if (!logFile.exists()) {
logFile.getParentFile().mkdirs();
logFile.createNewFile();
}
logWriter = new PrintWriter(new FileOutputStream(logFile));
start();
} catch (IOException ignored) {
}
}
public void log(Date date, String tag, String msg) {
if (isAlive()) {
logNodes.add(new LogNode(date, tag, msg));
}
}
@Override
public void run() {
while (true) {
try {
LogNode node = logNodes.take();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
logWriter.println(String.format(
"%s %s.%s", dateFormat.format(node.date), node.tag, node.msg
));
logWriter.flush();
} catch (InterruptedException e) {
logWriter.flush();
logWriter.close();
return;
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.