我有使用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)))有人知道如何解决这个问题吗?
答案 0 :(得分:1)
首先,您尚未描述您正在尝试做什么以及为什么。
其次。尝试实现自己的互斥锁,你做错了。您尝试使用的变量甚至不是线程安全的。由于多个线程可能正在访问它,因此您无法知道它在任何时间点的状态。你应该使用AtomicBoolean。
http://developer.android.com/reference/java/util/concurrent/atomic/AtomicBoolean.html
有关多线程的详细介绍,请参阅此幻灯片。
答案 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线程中执行长操作(注释“这是一些长动作”):应该在单独的线程中执行