我正在使用ScheduledThreadPoolExecutor在每个fileIntervalInSeconds秒内创建一个文件:
executorService = new ScheduledThreadPoolExecutor(1);
executorService.scheduleAtFixedRate(new Runnable()
{
@Override
public void run()
{
File file = new File(fileName);
if (file.exists())
{
Log.debug("creating new file");
openFileWriter(file);
}
}
}, fileIntervalInSeconds, fileIntervalInSeconds, TimeUnit.SECONDS);
}
private void openFileWriter() throws FileSystemNotificationException
{
// 1 - close exist writer
writer.close();
// 2 - rename to backup file name
...
// 3 - create new file
FileWriter writerFile = new FileWriter(fileName, true);
writer = new PrintWriter(writerFile);
}
我一直在向文件写入警告消息:
private synchronized void writeLine(String line) throws InterruptedException
{
writer.println(line);
}
我的问题是:
答案 0 :(得分:4)
在写入文件之前检查文件是怎么回事。不需要后台线程或同步
private synchronized void writeLine(String line) {
if (!file.exists())
reopenWritingFile();
writer.println(line);
}
答案 1 :(得分:0)
您有两种选择:
示例:
volatile PrintWriter writer;
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock writeLock = lock.writeLock();
Lock readLock = lock.readLock();
private void openFileWriterWithLock() throws IOException {
if (writeLock.tryLock()) {
try {
// 1 - close exist writer
writer.close();
// 2 - rename to backup file name
//...
// 3 - create new file
FileWriter writerFile = new FileWriter(fileName, true);
writer = new PrintWriter(writerFile);
} finally {
writeLock.unlock();
}
}
}
private synchronized void writeLineWithLock(String line) throws InterruptedException {
readLock.lock();
try {
writer.println(line);
} finally {
readLock.unlock();
}
}
private void openFileWriterWithoutLock() throws IOException {
// 0. Note old file.
PrintWriter oldWriter = writer;
// 1. Create new file.
FileWriter writerFile = new FileWriter(fileName, true);
// 2. Swap the new one in.
writer = new PrintWriter(writerFile);
// 3 - close old writer
oldWriter.close();
}
private synchronized void writeLineWithoutLock(String line) throws InterruptedException {
writer.println(line);
}
答案 2 :(得分:0)
您可以在write方法中每小时创建一个新文件。对于时间检查,您会有一些轻微的开销,但这应该可以忽略不计。下面的示例将每小时创建一个新的日志文件,并以毫秒为单位添加到文件名的前面。您可以格式化适合您的时间。
public class LogWriter {
private long lastCreationTime;
PrintWriter writer;
String logFileName;
public LogWriter(String logFileName) {
this.logFileName = logFileName;
createLogFile(logFileName);
}
private void createLogFile(String fileName) {
if(writer != null) {
writer.close();
}
lastCreationTime = System.currentTimeMillis();
FileWriter writerFile;
try {
writerFile = new FileWriter(lastCreationTime + "_" + fileName, true);
writer = new PrintWriter(writerFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private synchronized void writeLine(String line) {
if(lastCreationTime < System.currentTimeMillis() - 3600000) {
createLogFile(logFileName);
}
writer.write(line);
}
}
答案 3 :(得分:0)
如何使用一个单独的线程来处理日志记录而不是那个相当复杂的构造?
public class Logger extends Thread {
private final LinkedBlockingQueue<String> linesToWrite = new LinkedBlockingQueue<>();
private final String filename;
private Logger(String filename) {
super("Logging thread");
this.filename = filename;
this.setDaemon(true);
this.setPriority(Thread.MIN_PRIORITY);
}
@Override
public void run() {
try (BufferedWriter out = new BufferedWriter(new FileWriter(filename, true))) {
String line;
while (this.isInterrupted() == false) {
line = linesToWrite.take();
out.write(line);
out.newLine();
out.flush();
}
} catch (InterruptedException e) {
} catch (IOException ex) {
System.out.println("Failed to access log file: " + ex);
}
}
public void log(final String line) {
this.linesToWrite.add(line);
}
然后初始化记录器一次:
final Logger logger = new Logger("test.log");
logger.start();
然后你可以在线程安全的方式从任何地方使用它:
logger.log("Test message");
您无需停止记录器,因为Java将使用try构造确保文件已正确关闭。但是如果你愿意,你可以这样停止:
logger.interrupt();
现在您可以以单线程方式执行所有文件操作,因为任何时候只有一个线程可以访问日志文件。