【问题标题】:Android: thread exiting with uncaught exceptionAndroid:线程以未捕获的异常退出
【发布时间】:2013-04-11 04:42:39
【问题描述】:

我遇到了问题,我找不到解决方案。当我通过蓝牙连接接收数据时,我的程序突然崩溃。我在单独的线程中接收数据,每个接收到的字节都保存在队列中。 我还有一个 TimerTask,它每 1 毫秒调用一次从队列中读取数据的方法,并在 UI 中刷新 TextBox。我的程序运行了一段时间,然后突然崩溃。请帮忙。以下是主要代码sn-ps。

public class MainActivity extends Activity
{       
    TextView myLabel1;
    volatile boolean stopWorker = false;


    public Queue<Byte> receiverQueue = new LinkedList<Byte>();
    protected byte[] receiverArray;
    private boolean newDataRead = false;

    //timer
    TimerTask mTimerTask;
    Timer timer = new Timer();  
    final Handler timerHandler = new Handler();
}

@Override
public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

myLabel1 = (TextView)findViewById(R.id.textView1);
//start with timer ticking after 1 sec, and give timer tick every 1ms

onTimerTick();
timer.schedule(mTimerTask, 1000, 1); 
}


//method for reading data from receiverQueue
protected void readDataFromReceiverBuffer() {
    //if receiverQueue is not empty, read data
    if(receiverQueue.isEmpty() == false) {
        //declaration of byte array receiverField size of receiverQueue
        receiverArray = new byte[receiverQueue.size()];
        //read bytes from queue until is empty
            for (int i = 0; receiverQueue.isEmpty() == false; i++) {
                //retrieves and removes the head of this queue, or returns null 
            receiverArray[i] = receiverQueue.poll();
            }
        //variable newData is set to true, when we read new data from queue
        newDataRead = true;
    }
}       


Thread dataReceiveThread = new Thread(new Runnable() {
    //received byte
    int receivedData;
    public void run() {
        while(!Thread.currentThread().isInterrupted() && !stopWorker) {

            try { 
                //read one byte from InputStream
                receivedData = mmInStream.read();
                //inserts received byte into this queue if it is possible 
                if(receivedData != -1)
                    receiverQueue.offer((byte)receivedData);
            }
            catch (IOException ex) {
                stopWorker = true;
            }           
            //Log.i(String.valueOf(receivedData), "valueOfReceivedData");
        }           
    }       
}); 

public void onTimerTick() {
mTimerTask = new TimerTask() {
    String temp;
    //this method is called 
        public void run() {
            //call method for read data from queue
            readDataFromReceiverBuffer();
            timerHandler.post(new Runnable() {
                public void run() {
                    //when new data has arrived, we update UI 
                if(newDataRead == true) {
                    //convert byte array to string
                    temp = new String(receiverArray, 0, receiverArray.length);
                     myLabel1.setText(temp);
                     newDataRead = false;
                }                               
                    }
                }); 
      }};    
}    

LogCat:

W/dalvikvm(12358): threadid=11: thread exiting with uncaught exception (group=0x40ab1210)
E/AndroidRuntime(12358): FATAL EXCEPTION: Timer-0
E/AndroidRuntime(12358): java.lang.ArrayIndexOutOfBoundsException: length=21; index=21
E/AndroidRuntime(12358):    at com.example.colibri2bb.MainActivity.readDataFromReceiverBuffer(MainActivity.java:195)
E/AndroidRuntime(12358):    at com.example.colibri2bb.MainActivity.readDataFromReceiverBuffer(MainActivity.java:195)
E/AndroidRuntime(12358):    at com.example.colibri2bb.MainActivity$3.run(MainActivity.java:230)
E/AndroidRuntime(12358):    at java.util.Timer$TimerImpl.run(Timer.java:284)

LogCat:

W/dalvikvm(17344): threadid=12: thread exiting with uncaught exception (group=0x40ab1210)
E/AndroidRuntime(17344): FATAL EXCEPTION: Timer-1
E/AndroidRuntime(17344): java.util.NoSuchElementException
E/AndroidRuntime(17344): atjava.util.LinkedList.removeFirstImpl(LinkedList.java:689)
E/AndroidRuntime(17344): at java.util.LinkedList.removeFirst(LinkedList.java:676)
E/AndroidRuntime(17344): at java.util.LinkedList.poll(LinkedList.java:895)
E/AndroidRuntime(17344):atcom.example.colibri2bb.MainActivity.readDataFromReceiverBuffer(MainActivity.java:196)
E/AndroidRuntime(17344): atcom.example.colibri2bb.MainActivity$3.run(MainActivity.java:231)
E/AndroidRuntime(17344): at java.util.Timer$TimerImpl.run(Timer.java:284)

【问题讨论】:

  • 请发布你的日志
  • 变量 newDataRead 应该被声明为 volatile。
  • receiverArray[i] = receiverQueue.poll();
  • 好吧,从您的错误中可以看出,receiverQueue.isEmpty() == truereceiverArray 似乎比 i 小一个空格

标签: java android


【解决方案1】:

您的receiverArray 使用队列的大小进行初始化,但随后队列在您读取它时扩展,最终得到的数据比您预期的要多。

你必须确保你没有读太多,很可能是通过根据大小测试索引(额外的数据将在下次执行readDataFromReceiverBuffer时读取)

你也可以分配一个更大的数组(但测试仍然是强制性的)

您的第二个问题可能是您的任务太长,因此对队列的一些重叠和并发访问。 (基本上,2个实例测试队列是否为空,都尝试从中读取,但只有一个元素)

我会使用带循环的线程,循环执行的时间测量,以及延迟到下一次需要执行的睡眠,而不是计时器。这将确保单一访问读取队列。

【讨论】:

    【解决方案2】:

    在您读取接收器队列时,是否有其他线程正在修改接收器队列并添加数据? 尝试改用这个 for 循环。它应该确保你不会越界。

    int queueSize = receiverQueue.size();
    receiverArray = new byte[queueSize ];
    for (int i = 0; i<queueSize; i++) {
       ...
    }
    

    【讨论】:

    • 谢谢。我认为这可能是原因。这现在有效,但我得到另一个错误。我发布了新的 LogCat。就像@njzk2 说的,这可能是因为任务太长而发生的?
    • 现在看来队列中的元素比原来少了...您可以在 for 循环中尝试这两个条件(队列不为空,并且 i
    • 您能否建议我同步所有线程的最佳方法是什么?我是对象编程的菜鸟,没有太多经验..
    • Java 并发是一个大课题。最简单的方法是使修改此对象的所有函数都“同步”(public synchronized void readDataFromReceiveBuffer()...) - 但访问此对象的所有函数都必须同步,而不仅仅是一些。有关更多信息,请参阅本指南:docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
    • 非常感谢,我会查看本指南。但就我而言,onTimerTick() 是唯一调用 readDataFromReceiveBuffer() 的方法。我认为在我的情况下是一个问题,计时器滴答声很快,当 readDataFromBuffer() 仍在执行时,它会从 onTimerTick() 再次调用 - 然后崩溃......
    【解决方案3】:

    您的问题在这里:java.lang.ArrayIndexOutOfBoundsException: length=21; index=21 MainActivity.readDataFromReceiverBuffer。 当您的数组仅包含 21 个元素时,您尝试为 receiverArray[21] 赋值!

    【讨论】:

      【解决方案4】:

      这可能是因为抛出的异常类型不是 IOException。捕获所有异常并查看 - 将 IOException 更改为 Exception。

      【讨论】:

        猜你喜欢
        • 2016-02-09
        • 1970-01-01
        • 2017-10-01
        • 1970-01-01
        • 2014-10-24
        • 1970-01-01
        • 2015-04-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多