如何同步线程:onTouchEvent和run()?

时间:2012-11-02 14:12:18

标签: java android mutex ontouchevent runnable

我有使用GraphicView扩展SurfaceView。我需要它来绘制图形。我还需要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 !!!!" );
            }

        }

    }

}

我使用互斥技术(我想)必须控制我的线程。但是在Log中我看到了以下内容:

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

但为什么?为什么第二个&#34; !!!跑!!!!&#34;在&#34;行动1&#34;之间运行和&#34;行动2&#34;什么时候互斥锁关闭?这是不可能的! :)))

我试着做下一个:

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

但......失败:))onTouchEvent根本不会运行:D)))有人知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

首先,您尚未描述您正在尝试做什么以及为什么

其次。尝试实现自己的互斥锁,你做错了。您尝试使用的变量甚至不是线程安全的。由于多个线程可能正在访问它,因此您无法知道它在任何时间点的状态。你应该使用AtomicBoolean。

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

有关多线程的详细介绍,请参阅此幻灯片。

Intro to multi-threading

答案 1 :(得分:1)

你必须同步对mutexOpened的访问:run()可能在你将它设置为false之前立即读取mutexOpened并且可能正在打印RUN!打印“行动1”后立即。

使用Java关键字synchronized来同步对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线程中执行长操作(注释“这是一些长动作”):应该在单独的线程中执行