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

为何lock.notify无法唤醒等待线程?蓝牙管理线程阻塞问题

问题原因分析

1. 主线程阻塞导致Handler任务无法执行

你创建的phandler默认关联构造函数所在线程的消息队列,如果BluetoothManager是在主线程初始化的,那phandler的Runnable会在主线程执行。而enableBluetooth中调用lock.wait()时,是在主线程的同步块里执行的——wait()会阻塞当前线程,主线程被卡死之后,消息队列完全无法处理后续的Runnable任务,循环检测代码自然停摆,notify()永远不会被调用。

2. 权限判断逻辑完全颠倒

你在enableBluetooth里的权限判断代码是:

if (ActivityCompat.checkSelfPermission(...) != PackageManager.PERMISSION_GRANTED) {
    // 执行开启蓝牙和wait的逻辑
}

这意味着只有权限未获取时才会进入同步块执行等待逻辑,但实际需要的是权限通过后才去开启蓝牙,这直接导致权限正常时根本不会触发等待逻辑,逻辑完全错误。

3. 线程模型设计错误

wait/notify机制要求等待方和通知方必须在不同线程运行,否则一旦等待方阻塞线程,通知方就没有执行机会。你的代码里等待方(enableBluetooth的wait)和通知方(Runnable的notify)都在同一个线程(主线程),必然造成死锁。

修复思路(不使用广播的情况下)
  • 把enableBluetooth中的等待逻辑放到子线程执行,避免阻塞主线程,让Handler的Runnable能正常在主线程轮询蓝牙状态。
  • 修正权限判断逻辑,改为权限通过时才执行开启蓝牙和等待逻辑。
  • 确保wait和notify的调用分别在不同线程,锁的获取与释放逻辑正确。

示例修正片段:

public void enableBluetooth() {
    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter == null) {
        return;
    }
    if (!mBluetoothAdapter.isEnabled()) {
        // 修正权限判断:权限通过才执行后续逻辑
        if (ActivityCompat.checkSelfPermission(MyApplication.getContext(), android.Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
            // 子线程执行等待逻辑,避免阻塞主线程
            new Thread(() -> {
                synchronized (lock) {
                    mBluetoothAdapter.enable();
                    Log.i(TAG, "等待蓝牙开启...");
                    try {
                        lock.wait();
                        Log.i(TAG, "蓝牙已开启");
                        isBluetoothOn = true;
                        // 回到主线程触发回调
                        handler.post(this::onBluetoothConnected);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    } else {
        isBluetoothOn = true;
        onBluetoothConnected();
    }
}

另外注意:BluetoothAdapter.enable()是异步操作,系统开启蓝牙需要时间,你设置的10秒轮询间隔太长,建议改成1秒左右,避免不必要的等待延迟。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:26:26