0

データを読み取ってサーバーに送信するために2つのスレッドを使用するアプリを使用しています。各スレッドはwhileループを実行します。queは、サーバーに送信するためにdequeされたコマンドのqueを保持します。このようにして、デキューされてサーバーに送信される多数のコマンドを1つずつ並べることができます。

コマンド送信者はそれ自体です

 class writeThread extends AsyncTask<Object, Object, Object>
 {
    byte[] buffer;
    LittleEndianDataOutputStream outputStream;
    @Override
    protected void onPreExecute() 
    {

    }
    @Override
    protected Object doInBackground(Object... params) 
    {
        try
        {
            buffer = new byte[4096];
            outputStream = new LittleEndianDataOutputStream(dataHolder.connection.getOutputStream());

            try
            {
                dataHolder.flags latestFlag;
                while (true)
                {
                    try 
                    {
                        latestFlag = dataHolder.sendFlags.remove();
                        ByteBuffer sendBytes = ByteBuffer.allocate(128);
                        sendBytes.order(ByteOrder.LITTLE_ENDIAN);
                        switch (latestFlag) 
                        {
                            case sendDataRequest:
                                sendBytes.putInt(20);
                                outputStream.write(sendBytes.array());
                                break;
                            case getSelectedData:
                                sendBytes.putInt(21);
                                sendBytes.put(dataHolder.latestSelected.getBytes());
                                outputStream.write(sendBytes.array());
                                break;
                            case disconnect:
                                sendBytes.putInt(254);
                                sendBytes.put(dataHolder.latestSelected.getBytes());
                                outputStream.write(sendBytes.array());
                                break;                                    

                        }


                    }
                    catch (NoSuchElementException ex){}
                }
            }
            catch (IOException ex) {}

        }
        catch (Exception ex){};
        return null;

    }


}

読み取りループはそのように見えます

     while (inputStream.read() > -1)

その結果、アプリは電話の処理能力の50%を占めることになります。ソケットリスニングとデータ送信を最適化する方法について何か提案はありますか?

注:はい、キューが空でないかどうかを確認するために、ifステートメントの代わりにキューにtrycatchを使用していることはわかっています。エラースローは最適化に役立たないと確信していますが、プロセッサが50%になるとは思いません。もう情報が必要な場合はお知らせください。

4

1 に答える 1

0

実装の問題は、基本的にビジーウェイトを実行していることです。送信するものがない場合は、すぐに例外ハンドラーに移動して再試行します。したがって、そのコアのすべてのCPUを使用します。

代わりに必要なのは、イベントが利用可能になるまで待つ方法です。HandlerThreadを作成し、そのスレッドに関連付けられているハンドラーを使用してデータストリームへの書き込みを処理することをお勧めします。

HandlerThread handlerThread = new HandlerThread("blah");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
    public boolean HandleMessage(Message msg) {
        switch (msg.what) {
            case sendDataRequest:
               ...
            case getSelectedData:
               ...
            case disconnect:
               ...
        }
    }
}

次に、適切なIDとデータを使用してメッセージを作成し、handler.sendMessage()を使用してそれらをハンドラーに送信します。

あるいは(そしておそらくもっと簡単に)、dataHolder.sendFlagsコレクションを現在のものではなくArrayBlockingQueueにした場合(私はArrayListまたは同様のものを推測していますか?)、次に、ArrayBlockingQueue.takeで次の要素を削除します()、何かが利用可能になるまで待機します(利用可能なすべてのCPU時間を占めるビジー待機を実行せずに)

于 2012-04-22T03:02:45.723 に答える