You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线程下通过BLE向Nordic开发板发送数据的性能优化咨询

BLE向Nordic开发板发送数据功能优化方案

现有代码核心问题梳理

  • 轮询+固定250ms休眠的等待逻辑大幅拉低发送吞吐量,无意义的空等占了大部分耗时
  • alert计数到2就强制重置可发送状态的逻辑,会导致未收到应答就发起下一次发送,是偶发丢包的核心原因
  • 循环没有增加连接状态判断、超时退出机制,蓝牙断连后会陷入死循环
  • 每次调用sendData都新建线程,频繁创建销毁线程增加额外开销
  • 未校验bluetoothGatt.writeCharacteristic的返回值,写入请求提交蓝牙栈失败时也会进入无意义的等待

具体优化方案

1. 替换轮询机制为事件驱动等待

用CountDownLatch替代原有AtomicBoolean做同步,避免无意义轮询,同时内置超时机制,避免死循环:
首先修改类成员变量:

// 替换原有AtomicBoolean getSendingState
private CountDownLatch sendAckLatch;
// 单次发送超时时间,可根据实际场景调整
private static final long SEND_TIMEOUT_MS = 1000;
// 最大重试次数
private static final int MAX_SEND_RETRY = 3;
// 复用发送线程,避免频繁创建新线程
private final ExecutorService sendExecutor = Executors.newSingleThreadExecutor();

修改发送逻辑:

public void sendData(final String text) {
    // 发送前先校验连接状态,异常直接返回
    if (connectionState != STATE_CONNECTED || bluetoothGatt == null) {
        // 可自行增加发送失败回调通知上层
        return;
    }
    // 仅在连接异常时调用refreshDeviceCache,不要每次发送都调用,避免蓝牙栈不稳定
    // refreshDeviceCache(bluetoothGatt);
    this.text = text;
    BluetoothGattService bluetoothGattService = bluetoothGatt.getService(UUID.fromString(SampleGattAttributes.UUID_SERVICE_NORDIC));
    final BluetoothGattCharacteristic characteristicRx = bluetoothGattService.getCharacteristic(UUID_RX_CHARACTERISTIC);
    byte[] tx = text.getBytes(StandardCharsets.UTF_8);
    characteristicRx.setValue(tx);

    sendExecutor.execute(() -> {
        int retryCount = 0;
        while (retryCount < MAX_SEND_RETRY) {
            sendAckLatch = new CountDownLatch(1);
            // 校验写入请求是否成功提交到蓝牙栈
            boolean writeSubmitted = bluetoothGatt.writeCharacteristic(characteristicRx);
            if (!writeSubmitted) {
                retryCount++;
                continue;
            }
            try {
                // 等待应答,超时自动退出
                if (sendAckLatch.await(SEND_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                    // 发送成功直接结束
                    return;
                } else {
                    // 超时重试
                    retryCount++;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
        // 重试次数耗尽,触发发送失败回调
    });
}

修改接收应答逻辑:

if (UUID_TX_CHARACTERISTIC.equals(characteristic.getUuid())) {
    Log.w("NOTIFICATION", Arrays.toString(characteristic.getValue()));
    intent.putExtra(EXTRA_DATA, Arrays.toString(characteristic.getValue()));
    byte[] bytes = characteristic.getValue();
    incomingDataAsString = new String(bytes);
    // 收到应答后唤醒发送线程
    if (sendAckLatch != null) {
        sendAckLatch.countDown();
    }
}

2. 额外性能优化点

  • 分包处理:BLE默认MTU为23字节,单次最多发送20字节有效数据,如果发送的text长度超过20字节,需要自行实现分包逻辑,每个分包单独等待应答
  • 协商更大MTU:GATT连接成功后调用bluetoothGatt.requestMtu(512),和开发板协商更大的传输单元,减少发送次数,大幅提升吞吐量
  • 增加断连监听:收到ACTION_GATT_DISCONNECTED广播时直接终止所有待发送任务,清空发送队列,避免死循环
  • 实现发送队列:如果有高频多次发送需求,不要每次调用sendData就单独发起任务,用队列缓存待发送数据,前一个发送完成后自动取下一个发送,避免多个发送任务冲突

内容的提问来源于stack exchange,提问作者Thomassek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 16:15:04