避免线程已经启动异常(Android)

时间:2015-08-07 16:55:22

标签: java android thread-safety surfaceview

    java.lang.IllegalThreadStateException: Thread already started
        at java.lang.Thread.checkNotStarted(Thread.java:849)
        at java.lang.Thread.start(Thread.java:1059)
        at com.name.MainActivity$MenuView$1.surfaceCreated(MainActivity.java:496)

我该如何避免这种情况?我有一个内部类MenuView,它扩展了SurfaceView。它更新线程上的画布。 onSurfaceCreated()我启动线程,onSurfaceDestroyed()我调用thread.join()来停止线程。但是,如果弹出Google Play登录窗口,并且当它处于焦点时我按下主页按钮,然后重新打开该应用程序。我收到一个强制关闭错误和我在上面发布的异常。

holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                allow_thread_to_run = true;
                boolean retry = true;
                while (retry) {
                    if (t!=null && !t.isAlive()) {
                        t.start();
                        retry = false;
                    }
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                allow_thread_to_run = false;
                boolean retry = true;
                if(t!=null && t.isAlive()) {
                    while (retry) {
                        try {
                            t.join();
                            retry = false;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

    }

那么为什么这个Google Play窗口会成为焦点,导致我的主题开始两次。从我看到的情况来看,我的设置有必要的检查isAlive(),以确保避免这种情况!

1 个答案:

答案 0 :(得分:1)

我同意@ adelphus的观点。如果你关心Thread calss的代码,你会发现.Every Thread对象有一个标志,反映这个Thread是否已经启动。

boolean hasBeenStarted = false;

一旦调用start()方法,它将检查状态并更改是否为false,否则抛出异常,就像你得到的那样。看,

public synchronized void start() {
    checkNotStarted();

    hasBeenStarted = true;

    nativeCreate(this, stackSize, daemon);
}

之后,国家永远不会改变。当你再次调用start()时,它会抛出异常。