我正在开发一个Android项目,其中来自源的数据使用opengl呈现给用户,为了使其工作,我使用Thread从源读取数据,然后将这些数据存储在BlockingQueue上FIFO,然后弹出GLRenderer线程上的数据。我使用BlockingQueue来处理生产者/消费者场景。
只要向用户呈现只有一种类型的数据,一切正常。
例如,假设我必须使用数据类型,DATA A和DATA B,这两种类型都是从同一个源读取并使用Id标记选择的。为了独立处理每种数据类型,我使用了2个阅读线程。这些线程访问相同的对象方法当然是同步的以避免干扰,然后读取的数据分别存储在BlockingQueue A和BlockingQueue B上,并由GLRenderer A和GLRenderer B读取以同时显示2种类型的数据。屏幕。
我目前面临的问题是,数据A以随机方式与数据B交换,因此几乎不可能在屏幕上分别看到两种类型的数据。
以下是每个相关块的代码。
ReadingTask:
private class ReadDataTask extends AsyncTask<Void, Void, Void> {
private BlockingQueue<short[]> mFIFO;
private byte mDeviceID;
private boolean mIsDataShifted;
public ReadDataTask(BlockingQueue<short[]> fifo, byte deviceID, boolean shiftData) {
mFIFO = fifo;
mDeviceID = deviceID;
mIsDataShifted = shiftData;
}
@Override
protected Void doInBackground(Void... params) {
try {
while(true) {
if(isCancelled())
return null;
mFIFO.put(mCAL.readData(mDeviceID, mIsDataShifted));
Log.i("COM", "Thread " + mId + ":Reading...");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
return null;
}
}
}
希望你能帮助我。
更新
我发现我的问题存在一些混淆,所以我会试着澄清更多的问题。
“阅读任务”是上面提到的AsyncTask,通过这个任务,我从一个名为“Source”的IO端口获取了一些数据。对于读取IO端口的每个线程,对象mCAL是相同的,并且其类的方法都是同步的(例如,读取和写入不能同时发生)。 mDeviceID和mIsDataShifted字段作为参数传递,用于AsyncTask先前执行的初始化,“Reading Task”的每个实例使用mDeviceID和mIsDataShifted的不同值。 BlockingQueue mFIFO也作为参数传递给“ReadingTask”,并且对于此Thread的每个实例都是不同的。所以基本上我有2个OpenGL线程实例,2个ReadingTask线程实例和1个mCAL对象实例,它们在当前运行的所有可能“ReadingTasks”之间共享。
另外,我做了一些测试,我注意到每次“ReadingTask”线程的一个实例连续多次调用mCAL.readData()方法时,数据从一个OpenGL视图交换到另一个,所以我想这个问题涉及BlockingQueue FIFO put()方法(也许它必须在同步方法中调用?)。
这是CAL_Interface类:
public class CAL_Interface {
static
{
System.loadLibrary("FPGA_USB");
System.loadLibrary("CAL");
}
/**
* Set the properties for the data acquisition, such as the length of the data to
* acquire and the sampling frequency at which the data is being processed.
*
* @return
*/
public native int setAcquisitionProperties(int dataLength, double samplingFreq);
/**
* Configure the USB Chip and program the FPGA (if possible).
*
* @param fpgaModel
* @return
*/
public native int configureUSB(int fpgaModel);
/**
* Initialize the USB Channel.
*
* @return
*/
public native int initUSBChannel();
/**
* Send a SCPI Command to configure the Hardware Registers.
*
* @param cmd SCPI Command.
* @param deviceID Device Identifier.
*
* @return Error Flag: 0 when success. 1 when error.
*
*/
public native int sendCommand2FPGA(String cmd, byte deviceID);
/**
* Set the capture mode. For instance, choose between Oscilloscope data or
* Spectrum Analyzer data.
*
* @param config
* @return
*/
public native int setCaptureMode(byte config);
/**
* Receives the Device-Specific Data generated by the FPGA.
*
* @return Array containing the data.
*/
public native short[] getDataFromFPGA(byte deviceID, boolean shiftData);
/**
* Closes the USB Channel so the device can be properly de-initialized.
*
* @return
*/
public native int deinitUSBChannel();
/**
* Set the Internally Generated Signals Attributes
*
* @param channel
* @param amplitude
* @param frequency
* @return
*/
public native int setInternalSignalAttr(byte channel, byte wave, byte amplitude, double frequency);
public synchronized void openCommunicationChannel(int fpgaModel) {
/* Set the native constants for internal calculations */
setAcquisitionProperties(1024, 1e9);
/* Configure the USB Chip CyFX2 */
configureUSB(fpgaModel);
/* Initialize the USB Channel */
initUSBChannel();
}
public synchronized void closeCommunicationChannel() {
/* De-initialize the USB Channel */
deinitUSBChannel();
}
public synchronized short[] readData(byte deviceID, boolean shiftData) {
return getDataFromFPGA(deviceID, shiftData);
}
public synchronized void writeData(byte deviceID, String cmd) {
sendCommand2FPGA(cmd, deviceID);
}
}
此致