【问题标题】:How to synchronized threads: onTouchEvent and run()?如何同步线程:onTouchEvent 和 run()?
【发布时间】:2012-11-02 14:12:17
【问题描述】:

我有 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 !!!!" );
            }

        }

    }

}

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

!!! 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))) 有人知道如何解决这个问题吗?

【问题讨论】:

  • @PBrando,我认为您理解正确。它在第二个线程上运行,但我需要同步这些线程... :)

标签: java android mutex touch-event runnable


【解决方案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 线程中执行长操作(注释“这是一些长操作”):应该在单独的线程中执行

【讨论】:

  • 感谢您的建议!我尝试使用您的代码,但它给了我一个错误:“java.lang.IllegalMonitorStateException:对象未在 wait() 之前被线程锁定”,该错误是什么意思?
  • @JavaRunner 您是否将方法声明为“同步”运行?
【解决方案2】:

首先,你没有描述什么你想做什么以及为什么

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

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

有关多线程的良好介绍,请参阅此幻灯片集。

Intro to multi-threading

【讨论】:

    猜你喜欢
    • 2016-06-02
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2011-06-10
    • 2011-06-15
    • 1970-01-01
    相关资源
    最近更新 更多