如何处理UI线程和Android的另一个线程之间共享变量? [英] How to handle variables shared between UI thread and another thread in android?

查看:673
本文介绍了如何处理UI线程和Android的另一个线程之间共享变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想开发Android的音频处理相关的应用程序。我有一个线程(不是UI线程),其中我做的操作。我需要更新操作的结果,同时它仍在继续。出于同样的我使用的是处理程序。我只是用一个吐司显示处理程序中的结果。截至目前我的线程继续单独第一次运行并显示在第一个结果后,因为没有更新其结果线程也不再运行。我刚刚才知道,在修改这个主题和UI共享变量,我需要两个线程同步。我对么?如果是的话我怎么能实现呢?

谢谢!

修改

我张贴这是在我的线程和我的处理程序运行的方法的一个组成部分。

 而(fulldatabuffcnt + 200℃= fulldatabuffer.size())
        {
            双[] = windowdata新的双[200];
             classlabel = 0;
             // classlabel_new = 0;
             INT windowcnt = 0;
                对于(INT H = fulldatabuffcnt; H< fulldatabuffcnt + 200; H ++)
                {
                        windowdata [windowcnt] = fulldatabuffer.get(H);
                        windowcnt ++;
                }                MFCCcoeffs = mfcc_inst.getParameters(windowdata);
                classlabel = likeli_ref.llhmain(MFCCcoeffs);            尝试{
                out.writeInt(fulldatabuffer.size());                }赶上(IOException异常E1)
                {
                    // TODO自动生成catch块
                    e1.printStackTrace();
                }            classlabel_array [ecount] = classlabel;
            ecount ++;            如果(ecount == 25)
                {
                      同步(SharedData.globalInstance){                            SharedData.globalInstance.classlabel_new = occurence(classlabel_array); //< - 共享变量classlabel_new得到修改
                        }
                      尝试{
                            out_max.writeInt(SharedData.globalInstance.classlabel_new);
                            }赶上(IOException异常E1){
                                // TODO自动生成catch块
                                e1.printStackTrace();
                            }                      ecount = 0;
                     uiCallback.sendEmptyMessage(0);
                }
        fulldatabuffcnt = fulldatabuffcnt + 80;
        }
       如果(fulldatabuffcnt + 200 GT; fulldatabuffer.size()){           AppLog.logString(设置calclating线程为空);
           calculatingThread = NULL;
       }
       尝试{
           out.close();           out_max.close();
        }
       赶上(IOException异常E)
        {
           e.printStackTrace();
        }   }
   私人处理程序uiCallback =新的处理程序(){         公共无效的handleMessage(消息MSG){
            INT label_handler;
            同步(SharedData.globalInstance){
               label_handler = SharedData.globalInstance.classlabel_new;
            }             Toast.makeText(MFCC2Activity.this,分类标签+ label_handler,Toast.LENGTH_SHORT).show(); //< - 试图访问classlabel_new         }     };


解决方案

是的,你应该同步,以确保您的UI线程不访问由自己的线程只是部分设置的变量。

我建议你有一个单独的对象是什么包含了所有你需要两个线程之间传递变量/数据等。例如,假设您需要共享一个字符串和你自己的线程和UI线程之间的两倍。一个单身的,例如创建一个类SharedData。

 类SharedData {
    公共字符串ASTRING;
    公共双aDouble;
    公共静态SharedData globalInstance =新SharedData();
}

然后在你自己的线程要设置数据

 同步(SharedData.globalInstance){
    SharedData.globalInstance.aString =一些字符串;
    SharedData.aDouble = 42.0;
}

和在你的UI线程

 字符串ASTRING;
双aDouble;
同步(SharedData.globalInstance){
    ASTRING = SharedData.globalInstance.aString;
    aDouuble = SharedData.aDouble;
}
//做点什么ASTRING和aDouble

如果你那样做的话,会不会被UI线程读取与部分组数据的任何问题。

I am trying to develop an audio processing related app in android. I have one thread(not the UI thread) in which I am doing an operation. I need to update the result of the operation while it is still going on. For the same I am using a Handler. I am just using a Toast to display the result inside the handler. As of now my thread is continuing to run for the first time alone and after displaying the first result the thread doesn't run anymore because of which results are not updated. I just came to know that while modifying variables shared by this Thread and the UI, I need to synchronize both the threads. Am I correct? If so how can I achieve it?

Thanks!!

EDIT

I am posting a part of the method which is running in my thread and my handler.

        while(fulldatabuffcnt+200<=fulldatabuffer.size())  
        {   
            double[] windowdata=new double[200];
             classlabel=0;
             //classlabel_new=0;
             int windowcnt=0;
                for (int h=fulldatabuffcnt;h<fulldatabuffcnt+200;h++)
                {
                        windowdata[windowcnt]=fulldatabuffer.get(h);
                        windowcnt++;
                }

                MFCCcoeffs=mfcc_inst.getParameters(windowdata);
                classlabel=likeli_ref.llhmain(MFCCcoeffs);

            try {
                out.writeInt(fulldatabuffer.size());

                } catch (IOException e1) 
                {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

            classlabel_array[ecount]=classlabel;
            ecount++;

            if (ecount==25)
                {
                      synchronized(SharedData.globalInstance) {

                            SharedData.globalInstance.classlabel_new =occurence(classlabel_array);//<--shared variable classlabel_new getting modified
                        }
                      try {
                            out_max.writeInt(SharedData.globalInstance.classlabel_new);
                            } catch (IOException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            }

                      ecount=0;
                     uiCallback.sendEmptyMessage(0);


                }


        fulldatabuffcnt=fulldatabuffcnt+80;
        }
       if(fulldatabuffcnt+200>fulldatabuffer.size()){

           AppLog.logString("Setting calclating thread to null");
           calculatingThread = null;
       }
       try {
           out.close();

           out_max.close();
        } 
       catch (IOException e) 
        {
           e.printStackTrace();
        } 

   }


   private Handler uiCallback = new Handler () {

         public void handleMessage (Message msg) {
            int label_handler;
            synchronized(SharedData.globalInstance) {
               label_handler=SharedData.globalInstance.classlabel_new;
            }

             Toast.makeText(MFCC2Activity.this, "Classified label" +label_handler, Toast.LENGTH_SHORT).show();//<--trying to access classlabel_new

         }

     };

解决方案

Yes, you should synchronize to make sure that your UI thread doesn't access variables that are only partially set up by your own thread.

I suggest that you have a singleton object what contains all the variables/data etc that you need to pass between the two threads. For example, suppose you need to share a string and a double between your own thread and the UI thread. Create a class SharedData with a singleton, e.g.

class SharedData {
    public String aString;
    public double aDouble;
    public static SharedData globalInstance = new SharedData();
}

Then in your own thread where you want to set the data

synchronized(SharedData.globalInstance) {
    SharedData.globalInstance.aString = "some string";
    SharedData.aDouble = 42.0;
}

and in your UI thread

String aString;
double aDouble;
synchronized(SharedData.globalInstance) {
    aString = SharedData.globalInstance.aString;
    aDouuble = SharedData.aDouble;
}
// do something with aString and aDouble

If you do it like that, then there won't be any problems relating to partially set data being read by the UI thread.

这篇关于如何处理UI线程和Android的另一个线程之间共享变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆