0

Androidでオーディオ処理関連のアプリを開発しようとしています。操作を行っている 1 つのスレッド (UI スレッドではない) があります。操作がまだ進行中に、操作の結果を更新する必要があります。同じために、ハンドラーを使用しています。Toast を使用してハンドラー内に結果を表示しています。今のところ、私のスレッドは初めて単独で実行され続けており、最初の結果を表示した後、結果が更新されないため、スレッドはもう実行されません。このスレッドと UI で共有される変数を変更しているときに、両方のスレッドを同期する必要があることを知りました。私は正しいですか?もしそうなら、どうすればそれを達成できますか?

ありがとう!!

編集

スレッドとハンドラーで実行されているメソッドの一部を投稿しています。

        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

         }

     };
4

1 に答える 1

1

はい、同期して、UI スレッドが独自のスレッドによって部分的にしか設定されていない変数にアクセスしないようにする必要があります。

2 つのスレッド間で渡す必要があるすべての変数/データなどを含むシングルトン オブジェクトを用意することをお勧めします。たとえば、独自のスレッドと UI スレッドの間で string と double を共有する必要があるとします。シングルトンでクラス SharedData を作成します。

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

次に、データを設定する独自のスレッドで

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

そしてあなたのUIスレッドで

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

そのようにすれば、部分的に設定されたデータが UI スレッドによって読み取られることに関連する問題は発生しません。

于 2013-05-20T12:22:46.110 に答える