android 写行为日志到SD卡 并发处理 异步写入数据到文件不影响界面响应时间

公司在做一个项目 要求记录用户行为,写行为日志文件到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 block
			e.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;
	}

	@Override
	public 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 直到整个程序结束。还有进过测试 能提升多少性能是否有这个必要。

android 写行为日志到SD卡 并发处理 异步写入数据到文件不影响界面响应时间,布布扣,bubuko.com

时间: 2024-10-02 22:21:22

android 写行为日志到SD卡 并发处理 异步写入数据到文件不影响界面响应时间的相关文章

保存android程序崩溃日志到SD卡

private boolean writeToSDCard(Throwable ex) { boolean isDealing = false; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { RandomAccessFile randomAccessFile = null; try { String fileName = SDCARDROOT + File.separator + "l

Android将数据库保存到SD卡的实现

??有时候为了需要,会将数据库保存到外部存储或者SD卡中(对于这种情况可以通过加密数据来避免数据被破解),比如一个应用支持多个数据,每个数据都需要有一个对应的数据库,并且数据库中的信息量特别大时,这显然更应该将数据库保存在外部存储或者SD卡中,因为RAM的大小是有限的:其次在写某些测试程序时将数据库保存在SD卡更方便查看数据库中的内容. ??Android通过SQLiteOpenHelper创建数据库时默认是将数据库保存在'/data/data/应用程序名/databases'目录下的,只需要在

Android 存储(本地存储 SD卡存储 SharedPreference SQLite ContentProvider)

本文出自:http://blog.csdn.net/dt235201314/article/details/73176149 源码下载欢迎Star(updating):https://github.com/JinBoy23520/CoderToDeveloperByTCLer 一丶慨述 本周的学习内容是Android存储,要求:数据库Sqlite相关操作,常用的文件存取方式,以及实用场景学习,主要学习Sqlite,SD卡文件操作,SharedPreference 二丶效果演示:         

Android - 通过系统数据库获取SD卡音乐媒体信息

当写一些东西(比如音乐播放器)的时候,就需要SD卡的mp3列表了-开始我是使用列文件来着,但是再获取文件的信息(歌手,专辑,图片,时长等..)很麻烦,所以直接用这个函数了- 1 private void getMusicPaths(){ 2 // 3 // 获取音乐列表 4 // 5 Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, M

Android下获取手机和SD卡的总空间和可用空间

获取SD卡的总空间和可用空间 File path = Environment.getExternalStorageDirectory(); StatFs stat = new StatFs(path.getPath()); long blockSize = stat.getBlockSize(); long totalBlocks = stat.getBlockCount(); long availableBlocks = stat.getAvailableBlocks(); long tota

Android中使用SQLiteOpenHelper管理SD卡中的数据库

使用Android中自带的SQLiteOpenHelper可以完成数据库的创建与管理,但有两点局限: (1)数据库创建在内存卡中,大小受限,创建位置位于/data/data/应用程序名/databases中(可使用Eclispe的DDMS查看). (2)如果无法获取Root权限,则无法直接查看创建的数据库. 鉴于上述限制及实际需要,打算使用SQLiteOpenHelper管理SD卡上的数据库,通过研究SQLiteOpenHelper的源码,发现其创建或打开数据库的代码位于getWritableD

android.uid.system无法读取SD卡信息

[Android]android.uid.system无法读取SD卡信息[转] 在AndroidManifest.xml中我们可以看到android:sharedUserId="android.uid.system"但是有了这句后,就无法对sd卡进行读写操作,比如在SD卡中创建一个新文件夹,是创建不成功的. 但是如果把android:sharedUserId="android.uid.system"注释掉,就可以在SD卡进行IO操作了. 在Settings中andr

android 建数据库 SQLite 存储sd 卡或者内存

android 创建数据库调用SQLiteOpenHelper,一般不直接操作SQLiteDatabase . 是通过SQLiteOpenHelper来获取 public class DBOpenHelper extends SQLiteOpenHelper { private static final int VERSION = 1;// 定义数据库版本 private static final String PATH = Environment .getExternalStorageDire

【Android】保存Bitmap到SD卡

1.打开读写SD卡的权限 需要在AndroidManifest.xml加入如下代码: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 第一种方法: public void saveBitmap(String bit