如何在将队列<T>添加到另一个类中时将队列内容写入文件



我有一个向Queue添加值的Listener类,我有另一个包含Queue并将其写入文件的类。这两个类都在后台线程中运行。

侦听器类

private AccelerometerQueue mLogQueue; //Queue class implements Runnable
private Thread mQueueThread; //Thread to run Runnable of Queue class
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    synchronized (this) {
        mLogQueue.addToQueue(
                new AccelerometerVector(
                        System.currentTimeMillis(),
                        sensorEvent.timestamp,
                        sensorEvent.values[0],
                        sensorEvent.values[1],
                        sensorEvent.values[2]
                )
        );

        mQueueThread = new Thread(mLogQueue);
        mQueueThread.start();
    }
}

队列类imlpements可运行并且具有此LinkedList

public void addToQueue(AccelerometerVector vector) {
    mQueue.add(vector);
}
public synchronized int getQueueSize(){
    return mQueue.size();
}
@Override
public void run() {
    try {
        mLogFile = createLogFile();
        mLogOutStream = new FileOutputStream(mLogFile, true);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    while (!mQueue.isEmpty()) {
        try {
            mLogOutStream.write(mQueue.poll().getDataStringLine().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (mLogFile.length() > AppConstants.LOG_FILE_MAX_SIZE) {
            try {
                reportCurrentLogFileIsFinished(mLogFile);
                mLogOutStream.flush();
                mLogOutStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                mLogOutStream = new FileOutputStream(createLogFile(), true);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}
private File createLogFile() {
    String datePart = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(new Date());
    String namePart = "log_" + datePart + ".csv";
    File folder = new File(Environment.getExternalStorageDirectory().toString()
            + File.separator + AppConstants.APP_LOG_FOLDER_NAME);
    folder.mkdirs();
    File file = new File(folder + File.separator + namePart);
    if (!file.exists()) { //create the file if not exist
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "Can not create file: " + file.getName());
        }
    }
    if (file.exists()) {
        return file;
    } else {
        return null;
    }
}

我的目标是将队列内容保存到存储中,文件的大小不应超过256Kb,当文件达到256Kb时,应该创建一个新文件。

该代码目前所做的是写入一些大小为2或3 Kb的文件,然后在createLogFile()方法中抛出异常,抱怨无法创建文件(我在Logcat中看到了这一点)。

问题是,我做错了什么,可能的解决方案是什么?

首先,我假设您正在使用一个同步的集合:

http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedList(java.util.List)

尝试重新打开文件可能是问题所在。假设有一个线程正在写入该文件,我建议您打开该文件并保持其打开状态。

最后,你有什么例外?

好的,我解决了这个问题。

第一个问题是我在onSensorChanged方法中启动了mQueueThread。这导致新线程在从onSensorChanged方法接收更新时启动,并导致内存泄漏或其他一些严重问题。所以我把它移到了构造函数。

其次,我将队列类型更改为ConcurrentLinkedQueue,但我没有任何解释。。。可能是另一种类型会做得更好。

最后,我将Runnable的实现更改为:

@Override
public void run() {
    while (true) {
        if (mLogOutStream != null && !mQueue.isEmpty()) {
            try {
                mLogOutStream.write(mQueue.poll().getDataStringLine().getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (mLogFile.length() > AppConstants.LOG_FILE_MAX_SIZE) {
                synchronized (this) {
                    reportCurrentLogFileIsFinished(mLogFile);
                    try {
                        if (mLogOutStream != null) {
                            mLogOutStream.flush();
                            mLogOutStream.close();
                            mLogOutStream = null;
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        mLogFile = createLogFile();
                        mLogOutStream = new FileOutputStream(mLogFile, true);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

这些变化解决了问题。希望这也能帮助其他人。

相关内容

  • 没有找到相关文章

最新更新