2014-02-24 14 views
0

有人可以解释什么是在这里发生什么线程被阻止?此处的线程对象用于画布和绘图图形,因此将在此图形线程上调用join()方法,以便它继续完成。而另一个线程被阻塞并等待。哪个线程是这个?哪个线程被阻塞等待线程连接()在SurfaceView的这个简短示例中完成?

如果surfaceView类在主UI线程上运行,那么UI将被阻塞,等待图形线程完成。这根本不符合逻辑。所以其他的解释是在这里有三个独立的线程。主要的UI线程,join()被调用的图形线程,以及第三个用于表面视图的线程在图形线程结束时被阻塞

实际上有三个线程在运行,而UI线程是不是被阻止的人?

无处在我的代码中,我是否为SurfaceView启动了一个新线程。我只实例化了一个SurfaceView对象。

随着代码的写入,看起来主UI线程被阻塞,等待图形线程完成。

如果SurfaceView对象在线程或AsyncTask内部实例化,那么它看起来更清晰。

//此代码位于SurfaceView类

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // can also put this code in surfaceChanged 
    running = true; 
    thread = new Thread(surfaceRunnable); 
    thread.start(); 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    running = false; 
    boolean retry = true; 
    while(retry) { 
     try { 
     thread.join(); 
     retry = false; 
     } catch(InterruptedException e) { 

     } 
    } 
+2

执行'thread.join()'的线程是被阻塞的线程,而不是'thread'表示的线程。 –

+0

是否意味着surfaceDestoryed被后台线程调用,而不是主UI线程? – Kevik

+0

如果将日志消息添加到某些代码('surfaceCreated()','surfaceDestroyed()','surfaceRunnable.run()',然后使用'adb logcat -v threadtime'查看logcat输出,则可以看到日志消息旁边的线程ID,这使得将活动映射到特定线程变得很容易。更好的办法是附上一个调试器,然后看看所有的线程是什么以及每个线程停止了什么 - 然后你就会知道不仅是什么,而且是为什么。 – fadden

回答

0

被阻止为UI线程线程的内部。用调试器证明这是个好主意。您可以通过查看SurfaceView.java的源代码来进行确认(如果在Eclipse中,则在光标位于文本SurfaceView上时点击F3)。特别是:

surfaceDestroyed()的回调是从SurfaceView.updateWindow()称为:

private void updateWindow(boolean force, boolean redrawNeeded) { 
    ... 
    callbacks = getSurfaceCallbacks(); 
    for (SurfaceHolder.Callback c : callbacks) { 
     c.surfaceDestroyed(mSurfaceHolder); 
    } 

updateWindow()是从Handler衍生和分配匿名类叫mHandler

final Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
      case KEEP_SCREEN_ON_MSG: { 
       setKeepScreenOn(msg.arg1 != 0); 
      } break; 
      case GET_NEW_SURFACE_MSG: { 
       handleGetNewSurface(); 
      } break; 
      case UPDATE_WINDOW_MSG: { 
       updateWindow(false, false); 
      } break; 
     } 
    } 
}; 

注意,这mHandler对象是在构造SurfaceView对象时构建的,这发生在UI线程上。并注意Handler构造函数将Handler绑定到与当前线程(UI线程)关联的Looper。因此handleMesssage()在该Looper上运行,这是UI线程的Looper。因此,在UI线程上调用updateWindow()

updateWindow()在文件中也被称为其他几次,并且大多数时候很容易推断出它是从UI线程调用的。