0

私のコンポーネントはサードパーティのコンポーネントに統合されています。onTick()優先度の高いThreadサードパーティコンポーネントによって呼び出されるメソッドをオーバーライドする必要があります。サンプルコード:

@Override
public void onTick() {

    // do many useful operations

}

特定のシナリオではonTick()、結果が破棄されるため、このメソッドはこれらの「多くの有用な操作」を実行しないはずです。実際、その場合、の機能onTick()はまったく必要ありませんが、サードパーティコンポーネントは「一時停止」または「スリープ」機能を提供しません。onTick() いつも電話します。これは、これらの特別な期間にCPU時間が不必要に消費されることを意味します。

最も簡単な解決策は、適切なブロック内でシグナルを送信しonTick()、そのスレッドをスリープ状態にすることです。ただし、サードパーティコンポーネントのドキュメントには、コンポーネントを任意に待機状態に送信してはならないと記載されています。Object.wait()synchronizedThread

この場合、CPUリソースを節約するための解決策はありますか?つまり、他の人にCPUを使用させるには?次のソリューションを作成しましたが、CPUを節約できるかどうかはわかりません。(それでも、少なくとも、の「便利な操作」セクションで使用される他のリソースを節約する必要がありますonTick())。

@Override
public void onTick() {

        // mJustUnpaused is volatile. Race condition, but probably harmless (?)
        if (mJustUnpaused) { 
            mJustUnpaused = false;
            // THREAD_PRIORITY_DISPLAY is the original 
            // priority used by the 3rd party Thread
            Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
        }

        if (!mRunningAllowed) {
            return;
        }

        if (mPauseRequested) { // mPauseRequested is declared as volatile
            synchronized (mPauseLock) {                 
                if (mRunningAllowed && mPauseRequested) {                       
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    mRunningAllowed = false;
                    mPauseLock.notify();
                }
            }               
            return;
        }

        // do many useful operations
}

一時停止/一時停止解除の方法(最初の方法はブロックされ、2番目の方法はブロックされません):

public void pauseWork() {
    synchronized (mPauseLock) {
        if (mRunningAllowed && !mPauseRequested) {
            mPauseRequested = true;
            while (mRunningAllowed) {
                try {
                    mPauseLock.wait();
                } catch (InterruptedException e) {}
            }
        } else {
            Log.d("RPT", "Already paused or pausing");
        }
    }
}

public void unpauseWork() {
    synchronized (mPauseLock) {
        if (!mRunningAllowed) {
            mRunningAllowed = true;
            mPauseRequested = false;
            mJustUnpaused = true;
        } else {
            Log.d("RPT", "No need to unpause");
        }
    }
}

3つの質問:

  1. CPU時間を節約するためのより良い方法はありますか?
  2. 他のすべてに関係なく、上記のコードは(同期およびその他のプログラミングの観点から)正しいですか?
  3. 少し話題から外れていますが、専用の質問に値するとは思いません。スレッドの優先度を変更すると、大きなオーバーヘッドが発生しますか?そのような行為を行うことができる場合の一般的なガイドラインはありますか?(たとえば、どのくらいの頻度で実行できるかなど)
4

1 に答える 1

2

CPU時間を節約するためのより良い方法はありますか?

私はそこにあるものを気にすることさえしません。私はChrisStrattonに同意します。実際の作業は避け、上記の他のコードの残りを削除してください。onTick()次に、Traceviewを使用して、何もしない呼び出しのオーバーヘッドが目立つかどうかを確認します。ほとんどの場合、そうではありません。

ただし、スレッドの優先度も変更したい

私がシナリオを正しく理解していれば、それはあなたのスレッドではないので、それは良い考えではありません。さらに、ライブラリが1秒間に約30回呼び出すようにコード化されているかのTimerように、スレッドの優先度に比較的影響されないようなものを使用している可能性があります。

他のすべてに関係なく、上記のコードは(同期およびその他のプログラミングの観点から)正しいですか?

個人的には、低レベル//ではなく、とからのものを使用java.util.concurrentします。ダグ・リーは私より賢いです。:-)java.util.concurrent.atomicwait()notify()volatile

于 2012-12-09T17:25:10.117 に答える