在这个SurfaceView的简短示例中,哪个线程被阻塞等待线程join()完成?

时间:2014-02-24 05:08:17

标签: java android multithreading graphics surfaceview

有人可以解释一下这个线程被阻止的内容是什么?这里的线程对象用于画布和绘图图形,在此图形线程上调用join()方法,因此它将继续完成。而另一个线程被阻止并等待。这个线程是什么?

如果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) {

        }
    }

1 个答案:

答案 0 :(得分:0)

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

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线程调用的。