我的问题不是特定于Java,但这是我用来实现我想要的语言。
我在Java中尝试蓝牙,并编写了一个简单的终端程序,即没有GUI界面,搜索附近的蓝牙设备并列出它们。我的代码如下:
import javax.bluetooth.*;
public class BluetoothTest implements DiscoveryListener{
private static boolean isAlive = true;
public static void main(String[] args) {
try {
LocalDevice ld = LocalDevice.getLocalDevice();
if (LocalDevice.isPowerOn()){
System.out.println("Power On.");
System.out.println("Friendly Name: " + ld.getFriendlyName());
System.out.println("Address: " + ld.getBluetoothAddress());
DiscoveryAgent da = ld.getDiscoveryAgent();
da.startInquiry(DiscoveryAgent.GIAC,new BluetoothTest());
while (isAlive){
/* Sleep */
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} else {
System.out.println("Power Off.");
}
} catch (BluetoothStateException e) {
System.out.println(e.toString());
}
}
public void setAlive(boolean status){
isAlive = status;
}
public void deviceDiscovered(RemoteDevice rd, DeviceClass dc){
try{
System.out.println(rd.getFriendlyName(true));
} catch (java.io.IOException e){
System.out.println(e.toString());
}
}
public void inquiryCompleted(int discType){
isAlive = false;
}
public void servicesDiscovered(int transID, ServiceRecord[] sr){
}
public void serviceSearchCompleted(int transID, int respCode){
}
}
DiscoveryAgent对象的startinquery()立即返回,任何被发现的设备都返回到我已经实现的DiscoveryListener接口。问题是,除非我包含while()循环,否则程序将在发现任何设备之前终止。
应用程序如何有效地保持驻留?它是通过有一个单独的"工作"线程和主线程产生工作线程,但自己睡觉,直到工人已经完成?
你可以使用Object wait/notify机制来保持main方法直到BluetoothTest通知一个公共对象锁。
只是一个伪代码,
定义一个静态final对象_mutex = new Object();
在调用startinquery后调用_mutex.wait();这将占用主线程。
In inquiryCompleted call _mutex.notify();这会释放主线程。
请注意,只有当startinquery创建一个新线程并调用回调方法时,这段代码才会工作。我不太了解DiscoverAgent类。因此,如果不是这种情况,上面的解决方案现在可能工作。
Java程序将一直运行,直到所有未标记为"守护进程"的线程退出。如果Main
线程退出并且没有其他线程运行,则程序将退出。如果生成了另一个不是"守护"线程的线程(或者DiscoveryAgent
在另一个线程中运行),那么Java将继续运行,直到该线程退出。将循环置于main中是一种很好的方法,尽管正如@jatanp所提到的,使用wait
/notify
更干净。
关于代码的几点注意事项:
-
这是奇怪的有你的主代码也是你的
DiscoveryListener
。我将把这个功能隔离在另一个类中:public class BluetoothTest { ... private static class OurListener implements DiscoveryListener { } }
- 因为你有2个线程正在从同一个变量
isAlive
中读取,它应该被标记为volatile
,或者你需要在它周围synchronize
。