【问题标题】:How to use MultiThreading in Android for an Event Handling Function (SensorListeners)如何在 Android 中将多线程用于事件处理功能(SensorListeners)
【发布时间】:2011-07-10 02:59:18
【问题描述】:

我的 Android 代码中有一个事件处理机制,可以将传感器值转储到文件中。现在,我在主 UI 线程中执行此操作,因此 UI 按钮响应非常缓慢,我想加快速度。

如何在事件处理函数上使用多线程?我正在尝试这样做:

  1. 创建一个全局变量 writeNow。
  2. 当传感器值发生变化时,设置WriteNow = true
  3. 在类中创建一个如下所示的线程:

    Thread thread1 = new Thread()  
    {  
      public void run()  
      {  
        if(writeNow == true)  
          {  
            try 
            {  
                fos.write(s.getBytes());  
            } 
            catch (IOException e) 
            {  
                 e.printStackTrace();  
            }  
            writeNow = false;  
          }  
      }  
     };  
    

因此,只要 writeNow 为真,它就会写入文件,然后将 WriteNow 设置为假。但是,我意识到这不是正确的方法,因为线程将执行一次然后停止执行。当我用while(true)和wait()尝试一个简单的例子时,我发现线程被中断了数百万次。

那么我如何将这个事件处理机制封装在一个线程中,以加快进程?

谢谢!

【问题讨论】:

    标签: java android multithreading events sensors


    【解决方案1】:

    您可以尝试以下方法之一:

    1. 看起来你正试图让你的 writer 线程一直运行;您可以做的是仅在需要时才生成线程。查看 Android 文档中handling expensive operation in the UI thread 的示例。

      这是该页面中的示例:

      public class MyActivity extends Activity {
      
          [ . . . ]
          // Need handler for callbacks to the UI thread
          final Handler mHandler = new Handler();
      
          // Create runnable for posting
          final Runnable mUpdateResults = new Runnable() {
              public void run() {
                  updateResultsInUi();
              }
          };
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
              [ . . . ]
          }
      
          protected void startLongRunningOperation() {
      
              // Fire off a thread to do some work that we shouldn't do directly in the UI thread
              Thread t = new Thread() {
                  public void run() {
                      mResults = doSomethingExpensive();
                      mHandler.post(mUpdateResults);
                  }
              };
              t.start();
          }
      
          private void updateResultsInUi() {
      
              // Back in the UI thread -- update our UI elements based on the data in mResults
              [ . . . ]
          }
      }
      

      因为一旦你完成写作,你看起来并没有在 UI 线程中做任何事情,你真的不需要为Handler 操心。但是您可能希望在文件写入后使用它来显示Toast

    2. 另一方面,如果你仍然想让一个线程运行,你可以让它sleep() 并定期唤醒并检查writeNow 的状态。

      Thread thread1 = new Thread()  
      {  
          public void run()  
          {  
              while(true)
              {
                  if(writeNow == true)  
                  {  
                      try 
                      {  
                          fos.write(s.getBytes());  
                      } 
                      catch (IOException e) 
                      {  
                           e.printStackTrace();  
                      }  
      
                      writeNow = false;  
                  }
      
                  try
                  {
                      Thread.sleep(100); //sleep for 100 ms
                  }
                  catch (InterruptedException e) 
                  {  
                       Log.d('', e.getMessage());  
                  }  
              }
          }  
       }; 
      

      请注意,这将很快变得复杂,如果您的线程在新数据进入时处于休眠状态并且当它唤醒时,您可能会丢失要写入的字节,即使接收到较新的数据并已覆盖先前的字节。你需要某种队列来管理它。

    3. 我不确定你用wait() 做了什么,但它应该也有效,事实上,这是解决涉及消费者和生产者问题的方法。这个想法是让你的线程在共享对象上同步和wait()(比如你的字节队列);当有数据可供写入时,第二个线程将在共享对象上调用notify(),并且写入器线程将被唤醒。然后编写器线程应该写入并重新循环。看看this tutorial

      至于你的线程的中断,你的线程可能会因为多种原因被中断,这就是为什么最好的做法(尤其是在使用wait() 时)以确保你检查的条件之前 您呼叫wait() 仍然有效,因为您可能因为呼叫notify()/notifyAll() 或因为中断而被唤醒。

    【讨论】:

    • 为什么我要睡100ms?为什么不一直运行一段时间(真)?我实际上尝试了这段代码,但 UI 响应能力根本没有改善......
    • 如果你的线程不是sleep(它不一定是100毫秒,这取决于你的应用程序)它不会给其他线程运行的机会——如果它是唯一的线程占用所有系统资源您会在设备上看到普遍的迟缓,因为 UI 线程和其他线程无法获得足够的 CPU 时间。看看busy waiting
    • 您尝试了方法#1 还是#3? wait/notify 是解决消费者-生产者问题的常用方法 - 请参阅我链接到的教程。 #1 中的代码非常完整,您只需将写入登录信息移至那里的run() 方法即可。如果这仍然没有帮助,那么您的问题出在其他地方。
    • 是的,我使用了等待/通知方法...它大大提高了响应能力..我使用了同步(对象)并等待/通知该对象,效果很好..谢谢很多!!
    【解决方案2】:
    Handler handler = null;
    
    handler = new Handler();
    
    //create another class for and make consrtuctor as u want. so that u can use that effectively.
    //for example.                                                      
    
    popupIndex = new IndexThread(handler,head, target,ltp,price,IndexNifty.this,columsView,call);           
    
    popupIndex.setColumnViewexit(columsView);
    handler.postDelayed(popupIndex, 300);
    
    
    //another class
    public IntraThread(Handler handler,String script,int target,int ltp,int price,Intraday intraday,TextView columsView,String call){
            super();
            this.target = target;
            this.ltp = ltp;
            this.price = price;     
            this.intraday = intraday;
            this.columsView = columsView;
            this.script= script;
            this.handler= handler;
            this.call= call;
    }
    
    public void run(){
    // write ur code here....
    }
    
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多