gpt4 book ai didi

java - Android/Java线程同步: while(true){} causing blocking

转载 作者:太空宇宙 更新时间:2023-11-04 12:33:46 25 4
gpt4 key购买 nike

我试图更好地理解我的 Android 应用程序中线程的行为。由于某种原因,当我在一个工作线程中使用 while(true) 时,该线程的 run 方法中在 while(true) 循环之前顺序存在的代码永远不会执行。需要明确的是,我不确定代码(toast 消息)是否实际上没有执行,或者 Android 操作系统处理线程同步的方式是否导致我的 Toast 消息不显示。这种行为似乎是某种阻塞,但我不明白为什么会发生这种情况。

我的应用程序使用 3 个线程:UI 线程(Android 应用程序中的默认/主线程)、一个在运行时从设备的 USB 端口无限读取数据的线程,以及一个通过来自 USB 读取线程的消息处理此数据的线程。问题似乎发生在我的 USBController 类中。当我注释掉无限 while 循环时,循环开始之前的所有 Toast 消息都显示得很好。 当我不注释掉我的 while(true) 时,不会显示任何 TOAST 消息!我对此感到非常困惑,我认为我误解了 Android 操作系统线程处理的一些基本原理。即使 while 循环会导致阻塞(我认为不会,因为它驻留在工作线程中),为什么不会触发 while 循环之前发生的 toast 消息? 这是同步问题吗?我是否滥用了 Android 的 Handler-Looper 系统?

代码如下。注意:我已经包含了主要 Activity 的相关部分和整个 USBController 类。我对此类的实现很大程度上依赖于此处找到的 USB 转串行库 mik3y/usb-serial-for-android 。我认为没有必要,但我已经包含了包含第三个线程 SensorDataBuffer 的类,该线程从线程 UsbController 接收消息。

UsbController.java

    public class UsbController extends Thread{
...
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DEFAULT); //sets thread to default queing priority
Looper.prepare();
Toast.makeText(mContext.getApplicationContext(), "Hello from UsbController's run method!", Toast.LENGTH_SHORT).show();

// **********************USB otg*******************************
//Obtain permission to use Android device's USB intent
PendingIntent mPermissionIntent;
mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);

// Find all available drivers from attached devices.
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x03EB, 0x2044, CdcAcmSerialDriver.class);
UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
UsbSerialProber prober = new UsbSerialProber(customTable);
List<UsbSerialDriver> availableDrivers = prober.findAllDrivers(manager);

if (availableDrivers.isEmpty()) {
Toast.makeText(mContext.getApplicationContext(), "No available USB drivers found",Toast.LENGTH_SHORT).show(); // Toast message for debugging
}
else { // open connection to first avail. driver
UsbSerialDriver driver = availableDrivers.get(0);
Toast.makeText(mContext.getApplicationContext(), "Driver found",Toast.LENGTH_SHORT).show(); // Toast message for debugging
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
Toast.makeText(mContext.getApplicationContext(), "Device Driver Opened",Toast.LENGTH_SHORT).show(); // Toast message for debugging
if (connection == null) { // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..)
Toast.makeText(mContext.getApplicationContext(),"Connection to device not allowed, need permissions",Toast.LENGTH_LONG).show();
manager.requestPermission(driver.getDevice(),mPermissionIntent); //conn test
if (manager.hasPermission(driver.getDevice())==true){
Toast.makeText(mContext.getApplicationContext(),"Permissions granted",Toast.LENGTH_SHORT).show();
}
}
else { // Read some data! Most have just one port (port 0).
List<UsbSerialPort> myPortList = driver.getPorts();
UsbSerialPort port = myPortList.get(0);
Toast.makeText(mContext.getApplicationContext(),"USB OTG Connection Established",Toast.LENGTH_SHORT).show();
try {
port.open(connection);
port.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // sets baud rate,databits, stopbits, & parity
port.setDTR(true); //necessary to make Arduino Micro begin running it's program
Toast.makeText(mContext.getApplicationContext(),"port opened, parameters set, DTR set",Toast.LENGTH_SHORT).show();
byte buffer[] = new byte[16];
String incompPacket = "";
Toast.makeText(mContext.getApplicationContext(), "hi again!"), Toast.LENGTH_LONG).show();
while (true){ //continuous loop to read data
numBytesRead = port.read(buffer, 100);
arduinoData = new String(buffer, "US-ASCII");
String raw = arduinoData.substring(0, numBytesRead);
if (numBytesRead > 0) {
...
}
}
} catch (IOException e) {
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
Looper.loop();
}
}

MainActivity.java

...
@Override
protected void onCreate(Bundle savedInstanceState) {

//Multi-threading
//Create thread to handle incoming data from USB Controller thread
SensorDataBuffer pressureDataBuffer = new SensorDataBuffer(MainActivity.this);
Thread bufferThread = new Thread(pressureDataBuffer);
bufferThread.start();

//Create USB Serial Worker thread which will continuously receive data
UsbController serialDataLink = new UsbController(PlayFrets.this);
Thread sensorMonitorThread = new Thread(serialDataLink);
sensorMonitorThread.start();
//Toast.makeText(this, "USB Controller thread started", Toast.LENGTH_SHORT).show();

//Build GUI
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //Removes action bar from display
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //Removes status bar from display

//Create AsyncTask to load the note files. A splash screen will be displayed while task is executing
new AsyncTask_NoteFileLoader(this).execute();
}
...

SensorDataBuffer.java

public class SensorDataBuffer extends Thread{

//Handler subclass which accepts messages one by one in
//the main activitiy's FIFO message que called a "Looper"
//The worker thread, sensorMonitor, runs UsbController in parallel
//with the UI thread and continuously formats and sends pressure sensor
//values read from the microcontroller to the Handler which updates the
//corresponding pressure state logic variables in the UI thread.
public void run(){
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO); //TODO:priority was previously more favorable, test this to ensure UI doesn't lag
Looper.prepare(); //create MessageQue to receive messages from USB Controller thread
UsbController.setHandler(bufferHandler);

bufferHandler = new Handler(Looper.myLooper()) {
//do stuff
};
Looper.loop();
}
}

最佳答案

使用 HandlerThreads、Handlers 和 Runnables 来代替怎么样?使您的代码更加干净且易于维护。

在你的 onCreate() 中只需创建其中几个:

HandlerThread usbThread = new HandlerThread("USBController");
usbThread.start();
usbHandler = new Handler(usbThread.getLooper());

HandlerThread sensorThread = new HandlerThread("SensorDataBuffer");
sensorThread.start();
sensorHandler = new Handler(sensorThread.getLooper());

然后创建 Runnables 并将它们发布到处理程序

usbHandler.post(new Runnable(){
run(){
//....
numBytesRead = port.read(buffer, 100);
if (numBytesRead > 0) {
sensorHandler.post(new Runnable(){run(){//doSomething}});
}
//....
if(isStillRunning)
usbHandler.post(this);
}
});

您可以让可运行的程序自行发布,它将永远运行。从内部,您可以将可运行对象发布到其他处理程序(例如主线程处理程序)以显示您的 Toast。

关于java - Android/Java线程同步: while(true){} causing blocking,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37559232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com