android 寫行為日誌到SD卡 並發處理 非同步寫入資料到檔案不影響介面回應時間

來源:互聯網
上載者:User

標籤:android開發   寫日誌   並發日誌   非同步寫入   不影響使用者體驗   


公司在做一個項目 要求記錄使用者行為,寫行為記錄檔到SD卡。實現思想 不影響介面使用者體驗,要時時記錄日誌 不能漏掉。

1.並發處理日誌 寫一個類負責管理各個線程傳過來的日誌資料,日誌資料放在隊列中等待寫線程去處理。這裡每次添加一條日誌資料都會檢查寫日誌線程是否在工作,同時為了並發處理傳過來的資料採用synchronized 同步:

   ConcurrentLinkedQueue 是基於連結節點的、安全執行緒的隊列。並發訪問不需要同步。因為它在隊列的尾部添加元素並從頭部刪除它們,所以只要不需要知道隊列的大小, ConcurrentLinkedQueue 對公用集合的共用訪問就可以工作得很好。收集關於隊列大小的資訊會很慢,需要遍曆隊列 建議使用   if(!queue.isEmpty()) 判斷是否空

 

package com.xx.log;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Date;import java.util.concurrent.ConcurrentLinkedQueue;import org.apache.log4j.Logger;import org.apache.log4j.spi.LoggerFactory;import android.util.Log;/** * 行為日誌記錄 * @author Administrator * */public class ActionLog { protected final static Logger logger = Logger.getLogger(ActionLog.class);public static String filePath="";public static ConcurrentLinkedQueue tempQueue=new ConcurrentLinkedQueue<Object>();/**     * 記錄基本資料 頭     * @param bi     */    public static synchronized void recordBaseInfoLog(BaseInfo bi){      tempQueue.add(bi);        if(!WriteThread.isWriteThreadLive){//監察寫線程是否工作中,沒有 則建立     new WriteThread().start();     }     }    /**     * 記錄行為資訊     * @param ai     */    public static synchronized void recordActionInfoLog(ActionInfo ai){    tempQueue.add(ai); if(!WriteThread.isWriteThreadLive){ new WriteThread().start(); }     }/** * 開啟記錄檔並寫入日誌 *  * @return * **/public static void recordStringLog(String text) {// 建立或開啟記錄檔  File file = new File(filePath);if (!file.exists()) { file.getParentFile().mkdirs();try {file.createNewFile();} catch (IOException e) {logger.error("行為日誌:在"+filePath+"建立檔案失敗!");e.printStackTrace();}}  try {FileWriter filerWriter = new FileWriter(file, true);//後面這個參數代表是不是要接上檔案中原來的資料,不進行覆蓋BufferedWriter bufWriter = new BufferedWriter(filerWriter);bufWriter.write(text);bufWriter.newLine();bufWriter.close();filerWriter.close();Log.d("行為日誌寫入成功",text);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}} /** * 判斷記錄檔是否存在 * @return */    public static boolean isExitLogFile(){    File file = new File(filePath);if (file.exists()&&file.length()>3){return true;}else{return false;}    }    /**     * 刪除記錄檔     */    public static void deleteLogFile(){   File file = new File(filePath);   if (file.exists()){   file.delete();   }    }  } 

2.非同步寫資料到檔案 不影響使用者體驗,不能因為寫日誌而有任何延遲.(實驗中如果一次寫入檔案中的資料比較小,即使同步寫入也不會太慢)為了達到這一目的首先考慮多線程另起一個線程專門負責來寫日誌到檔案中代碼如下:

 

package com.xx.log;import com.google.gson.Gson;public class WriteThread extends Thread{public static boolean isWriteThreadLive=false;//寫日誌線程是否已經在運行了 public WriteThread() {isWriteThreadLive=true;}@Overridepublic void run() {isWriteThreadLive=true;Gson gson=new Gson();       while(!ActionLog.tempQueue.isEmpty()){//對列不空時try {//寫日誌到SD卡ActionLog.recordStringLog(gson.toJson(ActionLog.tempQueue.poll())); } catch (Exception e) { e.printStackTrace(); }}    isWriteThreadLive=false;//隊列中的日誌都寫完了,關閉線程(也可以常開 要測試下)} }

其實我覺得 寫線程還是要一直保持運行可能更好,頻繁的建立線程對象應該也很耗費效能

好了以上代碼經過測試 可以達到多個線程大量並發寫日誌,可以保證按順序寫入到檔案中,而不影響使用者體驗 反應時間使用者感覺上可以忽略不計

由於時間問題 我還要寫上傳日誌的處理,寫日誌的功能暫時先這樣,以後有時間了研究下保持寫線程一直live 直到整個程式結束。還有進過測試 能提升多少效能是否有這個必要。

 

 

 


  

   

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.