java 异步写文件_java异步写日志到文件中实现代码

这篇博客详细介绍了如何在Java中实现异步写日志到文件,包括使用`LogWriter`类进行初始化、写入日志信息以及异常处理。通过示例代码展示了同步与异步写入文件的效率对比,强调了异步写入的优势。
摘要由CSDN通过智能技术生成

java异步写日志到文件中详解

实现代码:

package com.tydic.ESUtil;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.util.Properties;

public class LogWriter {

// 日志的配置文件

public static final String LOG_CONFIGFILE_NAME = "log.properties";

// 日志文件名在配置文件中的标签

public static final String LOGFILE_TAG_NAME = "logfile";

// 默认的日志文件的路径和文件名称

private final String DEFAULT_LOG_FILE_NAME = "./logtext.log";

// 该类的唯一的实例

private static LogWriter logWriter;

// 文件输出流

private PrintWriter writer;

// 日志文件名

private String logFileName;

/**

* 默认构造函数

*/

private LogWriter() throws LogException{

this.init();

}

private LogWriter(String fileName) throws LogException{

this.logFileName = fileName;

this.init();

}

/**

* 获取LogWriter的唯一实例。

* @return

* @throws LogException

*/

public synchronized static LogWriter getLogWriter()throws LogException{

if (logWriter == null){

logWriter = new LogWriter();

}

return logWriter;

}

public synchronized static LogWriter getLogWriter(String logFileName)throws LogException{

if (logWriter == null){

logWriter = new LogWriter(logFileName);

}

return logWriter;

}

/**

* 往日志文件中写一条日志信息

* 为了防止多线程同时操作(写)日志文件,造成文件”死锁”。使用synchronized关键字

* @param logMsg 日志消息

*/

public synchronized void log(String logMsg) {

this.writer.println(new java.util.Date() + ": " + logMsg);

}

/**

* 往日志文件中写一条异常信息

* 使用synchronized关键字。

* @param ex 待写入的异常

*/

public synchronized void log(Exception ex) {

writer.println(new java.util.Date() + ": ");

ex.printStackTrace(writer);

}

/**

* 初始化LogWriter

* @throws LogException

*/

private void init() throws LogException{

//如果用户没有在参数中指定日志文件名,则从配置文件中获取。

if (this.logFileName == null){

this.logFileName = this.getLogFileNameFromConfigFile();

//如果配置文件不存在或者也没有指定日志文件名,则用默认的日志文件名。

if (this.logFileName == null){

this.logFileName = DEFAULT_LOG_FILE_NAME;

}

}

File logFile = new File(this.logFileName);

try {

// 其中的FileWriter()中的第二个参数的含义是:是否在文件中追加内容

// PrintWriter()中的第二个参数的含义是:自动将数据flush到文件中

writer = new PrintWriter(new FileWriter(logFile, true), true);

System.out.println("日志文件的位置:" + logFile.getAbsolutePath());

} catch (IOException ex) {

String errmsg = "无法打开日志文件:" + logFile.getAbsolutePath();

// System.out.println(errmsg);

throw new LogException(errmsg, ex);

}

}

/**

* 从配置文件中取日志文件名

* @return

*/

private String getLogFileNameFromConfigFile() {

try {

Properties pro = new Properties();

//在类的当前位置,查找属性配置文件log.properties

InputStream fin = getClass().getResourceAsStream(LOG_CONFIGFILE_NAME);

if (fin != null){

pro.load(fin);//载入配置文件

fin.close();

return pro.getProperty(LOGFILE_TAG_NAME);

} else {

System.err.println("无法打开属性配置文件: log.properties" );

}

}catch (IOException ex) {

System.err.println("无法打开属性配置文件: log.properties" );

}

return null;

}

//关闭LogWriter

public void close() {

logWriter = null;

if (writer != null){

writer.close();

}

}

public static void main(String[] args) {

LogWriter logger = null;

try {

String fileName = "d:/temp/logger.log";

logger = LogWriter.getLogWriter(fileName);

// logger.log("First log!");

// logger.log("第二个日志信息");

// logger.log("Third log");

// logger.log("第四个日志信息");

String content="tableaA|device_number|13701010";

StringBuffer sb=new StringBuffer();

for(int i=0;i<1000000;i++){

sb.append(content).append(i).append(";\n");

}

content=sb.toString();

long startTime=System.currentTimeMillis();

logger.log(content);

long endTime=System.currentTimeMillis();

System.out.println("总消耗时间:"+(endTime-startTime));

logger.close();

// ReadFromFile.readFileByLines(fileName);

} catch (LogException e) {

e.printStackTrace();

}

}

}

package com.tydic.ESUtil;

public class AychWriter extends Thread {

private String content;

public AychWriter(String content){

this.content=content;

}

@Override

public void run(){

System.out.println("开始执行run()");

LogWriter logger = null;

String fileName = "d:/temp/logger.log";

long startTime=System.currentTimeMillis();

try {

logger = LogWriter.getLogWriter(fileName);

logger.log(this.content);

} catch (LogException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

long endTime=System.currentTimeMillis();

System.out.println("总消耗时间:"+(endTime-startTime));

}

}

测试类:

package com.tydic.ESUtil;

import java.io.FileWriter;

import java.io.IOException;

import org.junit.Test;

public class test_test {

/**

* 同步向指定文件尾部写入字符串

*/

public void testAppendMethodB(String fileName,String content) throws IOException{

try {

//打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件

FileWriter writer = new FileWriter(fileName, true);

writer.write(content);

writer.close();

} catch (IOException e) {

e.printStackTrace();

}

}

/**

*调用上面同步写方法

*/

@Test

public void testWriteTOFile() throws IOException{

String fileName = "d:\\test.txt";

String content="tableaA|device_number|13701010";

StringBuffer sb=new StringBuffer();

for(int i=0;i<100000;i++){

sb.append(content).append(i).append(";\n");

}

content=sb.toString();

long startTime=System.currentTimeMillis();

testAppendMethodB(fileName,content);

long endTime=System.currentTimeMillis();

System.out.println("总消耗时间:"+(endTime-startTime));

}

/**

* 异步调用写方法

* @throws IOException

* @throws InterruptedException

*/

@Test

public void testAsyncWriteTOFile() throws IOException, InterruptedException{

String fileName = "d:\\test.txt";

String content="tableaA|device_number|13701010";

StringBuffer sb=new StringBuffer();

for(int i=0;i<100000;i++){

sb.append(content).append(i).append(";\n");

}

content=sb.toString();

System.out.println("start write...");

new AychWriter(content).start();

System.out.println("write over...");

Thread.sleep(30000); //重要,如果主线程挂了,调用线程也停止了

System.out.println("main Thread over");

}

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值