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

但为什么??为什么是第二个“!!! RUN !!!!” 互斥锁关闭时在“ACTION 1”和“ACTION 2”之间运行?不可能!:)))

我试着下一步做:

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

但是... FAIL :)) 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!!!打印“ACTION 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 线程中执行长操作(注释“这是一些长操作”):应该在单独的线程中执行

于 2012-11-02T14:25:38.280 回答