【发布时间】:2017-09-27 03:15:33
【问题描述】:
我有一个线程从蓝牙流中读取数据,该线程将数据发送到主 UIThread 上的处理程序(基于Bluetooth Chat Sample)。
我发现了一个经常出现的线程问题。首先,一些代码供参考。
BluetoothService.java(只是读取传入数据流的部分。在此代码运行之前已正确设置)。
public void run() {
DebugLog.i("BluetoothService", "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
DebugLog.d("BluetoothService", new String(buffer, 0, bytes));
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
DebugLog.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
在我的主要活动中定义的处理程序(部分):
// The Handler that gets information back from the BluetoothService
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BluetoothService.MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
DebugLog.d("BluetoothHandler", readMessage);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
break;
}
}
};
当一个小的、连续的数据流进入mmInStream 时,我的问题就出现了。例如,'abcd'。如果 'abcd' 被一次性读取,则此代码正常运行,日志显示:
BluetoothService: BEGIN mConnectedThread
BluetoothService: abcd
BluetoothHandler: abcd
但如果该连续数据块被分成两部分读取,则第二组数据在到达处理程序时会覆盖第一组数据。这是我看到的一些示例日志。
BluetoothService: BEGIN mConnectedThread
BluetoothService: a
BluetoothService: bcd
BluetoothHandler: b
BluetoothHandler: bcd
或者:
BluetoothService: BEGIN mConnectedThread
BluetoothService: abc
BluetoothService: d
BluetoothHandler: dbc
BluetoothHandler: d
或者:
BluetoothService: BEGIN mConnectedThread
BluetoothService: ab
BluetoothService: cde
BluetoothHandler: cd
BluetoothHandler: cde
请注意,发送的第二条消息总是会覆盖第一条消息的数据,并且只覆盖最短消息的长度。此外,这两条消息总是在mHandler 处理第一条消息之前发送。
我猜我是一个公共缓冲区,在第一条消息被完全处理之前,某处被覆盖,但我不知道在哪里。有什么建议吗?
【问题讨论】:
标签: java android multithreading handler