android如何实现环形缓冲区

时间:2022-01-23 03:57:34

当我在开发一款关于音频通讯的sdk时通过搜集的资料,观看大神的博客,以及再加上个人的见解实现的环形缓冲区,思路是生产者消费者模式,用的是阻塞式队列BlockingQueue(详情参见http://blog.****.net/zlb824/article/details/7091814),我的buffer代码

/*
 * Copyright (C) 2013 liujian
 * 
 * Licensed under the GPL License Version 2.0;
 * you may not use this file except in compliance with the License.
 * 
 * If you have any question, please contact me.
 * 
 *************************************************************************
 **                   Author information                                **
 *************************************************************************
 ** Email: 1187502892@qq.com                                         **
 ** QQ   :<span style="font-family: Arial, Helvetica, sans-serif;">1187502892</span>
 *************************************************************************
 */
package com.zhifutong.zhangxinbao.tool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Buffer {
	private final static String TAG = "Buffer";

	private BlockingQueue<BufferData> mProducerQueue;
	private BlockingQueue<BufferData> mConsumeQueue;
	private int mBufferCount;
	private int mBufferSize;
	public static BufferData mBufferData = new BufferData(
			Global.bufferSizeInBytes);

	// when mData is null, means it is end of input
	public static class BufferData {
		public byte mData[];
		private int mFilledSize;
		private int mMaxBufferSize;
		private static BufferData sEmptyBuffer = new BufferData(0);

		public BufferData(int maxBufferSize) {
			mMaxBufferSize = maxBufferSize;
			reset();

			if (maxBufferSize > 0) {
				mMaxBufferSize = maxBufferSize;
				mData = new byte[mMaxBufferSize];
			} else {
				mData = null;
			}
		}

		public static BufferData getEmptyBuffer() {
			return sEmptyBuffer;
		}

		final public void reset() {
			mFilledSize = 0;
		}

		final public int getMaxBufferSize() {
			return mMaxBufferSize;
		}

		final public void setFilledSize(int size) {
			mFilledSize = size;
		}

		final public int getFilledSize() {
			return mFilledSize;
		}
	}

	public Buffer() {
		this(3, Global.bufferSizeInBytes);
	}

	public Buffer(int bufferCount, int bufferSize) {
		mBufferSize = bufferSize;
		mBufferCount = bufferCount;
		mProducerQueue = new LinkedBlockingQueue<BufferData>(mBufferCount);
		// we want to put the end buffer, so need to add 1
		mConsumeQueue = new LinkedBlockingQueue<BufferData>(mBufferCount);

		for (int i = 0; i < mBufferCount; ++i) {
			try {
				mProducerQueue.put(new BufferData(mBufferSize));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void reset() {
		int size = mProducerQueue.size();
		for (int i = 0; i < size; ++i) {
			BufferData data = mProducerQueue.peek();
			if (null == data || null == data.mData) {
				mProducerQueue.poll();
			}
		}

		size = mConsumeQueue.size();
		for (int i = 0; i < size; ++i) {
			BufferData data = mConsumeQueue.poll();
			if (null != data && null != data.mData) {
				mProducerQueue.add(data);
			}
		}

		// LogHelper.d(TAG, "reset ProducerQueue Size:" + mProducerQueue.size()
		// + "    ConsumeQueue Size:" + mConsumeQueue.size());
	}

	final public int getEmptyCount() {
		return mProducerQueue.size();
	}

	final public int getFullCount() {
		return mConsumeQueue.size();
	}

	public BufferData getEmpty() {
		// try {
		// if (mProducerQueue.size() == 0) {
		// for (int i = 0; i < mBufferCount; i++) {
		// mProducerQueue
		// .put(new BufferData(Global.bufferSizeInBytes));
		// }
		// }
		//
		// } catch (InterruptedException e1) {
		// // TODO Auto-generated catch block
		// e1.printStackTrace();
		// }
		return getImpl(mProducerQueue);
	}

	public boolean putEmpty(BufferData data) {
		return putImpl(data, mProducerQueue);
	}

	public BufferData getFull() {
		return getImpl(mConsumeQueue);
	}

	public boolean putFull(BufferData data) {
		return putImpl(data, mConsumeQueue);
	}

	private BufferData getImpl(BlockingQueue<BufferData> queue) {

		if (null != queue) {
			try {
				return queue.take();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	private boolean putImpl(BufferData data, BlockingQueue<BufferData> queue) {
		if (null != queue && null != data) {
			try {
				queue.put(data);
				return true;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

}
上面代码能够实现简单的环形缓冲区的角色,

把消费者用过的data在放入生产这种循环利用。