0

SurfaceViewを拡張するGraphicViewがあります。グラフィックを描くために必要です。onTouchEventも必要です。しかし、問題は...私はそれを説明する方法がわかりません:)ここに私のコードがあります:

public class GraphicView extends SurfaceView implements Runnable {

    private boolean mutexOpened = true;

    public boolean onTouchEvent( MotionEvent me ) {

        if ( mutexOpened ) {

            mutexOpened = false;

            Log.d( "mutex", "ACTION 1" );

            switch ( action ) {

                case MotionEvent.ACTION_DOWN: {

                    int rnd = new Random().nextInt( 40000 ) + 1000;
                    for ( int i = 0; i < rnd; i++ ) {} // it's some long action :)

                    Log.d( "mutex", "ACTION 2: down" );
                    break;

                }

            }

            Log.d( "mutex", "ACTION 2: end" );
            mutexOpened = true;

        }

    }

    public void run() {

        while ( true ) {

            if ( mutexOpened ) {        
                Log.d( "mutex", "!!! RUN !!!!" );
            }

        }

    }

}

私は(私が思うに)スレッドを制御しなければならないミューテックス技術を使用しています。しかし、ログには次のように表示されます。

!!! RUN !!!!
ACTION 1
!!! RUN !!!!
ACTION 2: down
ACTION 2: end

しかし、なぜ??なぜ2番目の「!!!RUN!!!!」ミューテックスが閉じているときに「アクション1」と「アクション2」の間で実行されますか?それは不可能だ!:)))

私は次にやろうとしました:

public void run() {
    while ( true ) {
        if ( mutexOpened ) {
            mutexOpened = false; // close mutex
            Log.d( "mutex", "!!! RUN !!!!" );
            mutexOpened = true; // open mutex
        }
    }
}

しかし...失敗:))onTouchEventはまったく実行されません:D)))誰かがこの問題を解決する方法を知っていますか?

4

2 に答える 2

1

まず第一に、あなたはあなたがをしようとしているのか、そしてその理由を説明していません。

第二に。あなたはあなた自身のミューテックスを実装しようとすることによってそれをすべて間違ってやっています。使用しようとしている変数は、スレッドセーフでもありません。複数のスレッドがアクセスしている可能性があるため、どの時点でもその状態を知る方法はありません。AtomicBooleanを使用する必要があります。

http://developer.android.com/reference/java/util/concurrent/atomic/AtomicBoolean.html

マルチスレッドの概要については、このスライドセットを参照してください。

マルチスレッドの概要

于 2012-11-02T14:25:30.637 に答える
1

mutexOpenedへのアクセスを同期する必要があります。run()は、falseに設定する直前にmutexOpenedを読み取っており、RUNを出力している可能性があります。「ACTION1」を印刷した直後。

同期されたJavaキーワードを使用して、mutexOpenedへのアクセスを同期します。run()では、待機フェーズ中にロックを解放するwait()を使用できます。

また、synchronizedキーワードを使用する場合は、変数mutexOpenedはまったく必要ありません。

public class GraphicView extends SurfaceView implements Runnable {

    synchronized public boolean onTouchEvent( MotionEvent me ) {


        Log.d( "mutex", "ACTION 1" );

        switch ( action ) {

            case MotionEvent.ACTION_DOWN: {

                int rnd = new Random().nextInt( 40000 ) + 1000;
                for ( int i = 0; i < rnd; i++ ) {} // it's some long action :)

                Log.d( "mutex", "ACTION 2: down" );
                break;

            }

        }

        Log.d( "mutex", "ACTION 2: end" );

    }


    synchronized public void run() {

        while ( true ) {
            wait(100); // Wait 100ms and release the lock
            Log.d( "mutex", "!!! RUN !!!!" );

        }

    }

}

また、GUIスレッドで長い操作を実行しないようにしてください(「これは長いアクションです」とコメントしています)。別のスレッドで実行する必要があります。

于 2012-11-02T14:25:38.280 に答える