java異步寫日志到文件中實(shí)現(xiàn)代碼
更新時(shí)間:2017年04月24日 11:19:10 作者:nature_fly088
這篇文章主要介紹了java異步寫日志到文件中實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下
java異步寫日志到文件中詳解
實(shí)現(xiàn)代碼:
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"; // 日志文件名在配置文件中的標(biāo)簽 public static final String LOGFILE_TAG_NAME = "logfile"; // 默認(rèn)的日志文件的路徑和文件名稱 private final String DEFAULT_LOG_FILE_NAME = "./logtext.log"; // 該類的唯一的實(shí)例 private static LogWriter logWriter; // 文件輸出流 private PrintWriter writer; // 日志文件名 private String logFileName; /** * 默認(rèn)構(gòu)造函數(shù) */ private LogWriter() throws LogException{ this.init(); } private LogWriter(String fileName) throws LogException{ this.logFileName = fileName; this.init(); } /** * 獲取LogWriter的唯一實(shí)例。 * @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; } /** * 往日志文件中寫一條日志信息 * 為了防止多線程同時(shí)操作(寫)日志文件,造成文件”死鎖”。使用synchronized關(guān)鍵字 * @param logMsg 日志消息 */ public synchronized void log(String logMsg) { this.writer.println(new java.util.Date() + ": " + logMsg); } /** * 往日志文件中寫一條異常信息 * 使用synchronized關(guān)鍵字。 * @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{ //如果用戶沒有在參數(shù)中指定日志文件名,則從配置文件中獲取。 if (this.logFileName == null){ this.logFileName = this.getLogFileNameFromConfigFile(); //如果配置文件不存在或者也沒有指定日志文件名,則用默認(rèn)的日志文件名。 if (this.logFileName == null){ this.logFileName = DEFAULT_LOG_FILE_NAME; } } File logFile = new File(this.logFileName); try { // 其中的FileWriter()中的第二個(gè)參數(shù)的含義是:是否在文件中追加內(nèi)容 // PrintWriter()中的第二個(gè)參數(shù)的含義是:自動將數(shù)據(jù)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(); //在類的當(dāng)前位置,查找屬性配置文件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; } //關(guān)閉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("第二個(gè)日志信息"); // logger.log("Third log"); // logger.log("第四個(gè)日志信息"); 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("總消耗時(shí)間:"+(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("開始執(zhí)行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("總消耗時(shí)間:"+(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 { //打開一個(gè)寫文件器,構(gòu)造函數(shù)中的第二個(gè)參數(shù)true表示以追加形式寫文件 FileWriter writer = new FileWriter(fileName, true); writer.write(content); writer.close(); } catch (IOException e) { e.printStackTrace(); } } /** *調(diào)用上面同步寫方法 */ @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("總消耗時(shí)間:"+(endTime-startTime)); } /** * 異步調(diào)用寫方法 * @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); //重要,如果主線程掛了,調(diào)用線程也停止了 System.out.println("main Thread over"); } }
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Java多線程Future松獲取異步任務(wù)結(jié)果輕松實(shí)現(xiàn)
這篇文章主要為大家介紹了Java多線程Future松獲取異步任務(wù)結(jié)果輕松實(shí)現(xiàn)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04詳解 Java繼承關(guān)系下的構(gòu)造方法調(diào)用
這篇文章主要介紹了詳解 Java繼承關(guān)系下的構(gòu)造方法調(diào)用的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10詳解Java如何實(shí)現(xiàn)數(shù)值校驗(yàn)的算法
給定一個(gè)字符串如何判斷它是否為數(shù)值類型?本文將帶著大家學(xué)習(xí)一下如何利用Java實(shí)現(xiàn)這個(gè)判斷算法,感興趣的小伙伴可以學(xué)習(xí)一下2022-04-04JAVA實(shí)現(xiàn)長連接(含心跳檢測Demo)
這篇文章主要介紹了JAVA實(shí)現(xiàn)長連接(含心跳檢測Demo),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10SpringCloud Alibaba Seata (收藏版)
Seata是一款開源的分布式事務(wù)解決方案,致力于在微服務(wù)架構(gòu)在提供高性能和簡單一樣的分布式事務(wù)服務(wù)。這篇文章主要介紹了SpringCloud Alibaba Seata 的相關(guān)知識,需要的朋友可以參考下2020-10-10