Thread.join()不起作用

时间:2013-06-14 15:59:13

标签: java android multithreading

这是补充java类(GFXSurface)。在这个类中,定义了第二个类,

public class GFXSurface extends Activity implements OnTouchListener {

    AnotherSurface ourSurfaceView;
    float x, y;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        ourSurfaceView = new AnotherSurface(this);
        ourSurfaceView.setOnTouchListener(this);
        x = 0;
        y = 0;
        setContentView(ourSurfaceView);
    }
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        ourSurfaceView.ourPause();
    }
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        ourSurfaceView.ourResume();
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        x = event.getX();
        y = event.getY();
        return true;  
    }

    /*------------------------Class within a class-------------------------------*/

    public class AnotherSurface extends SurfaceView implements Runnable {

        SurfaceHolder ourHolder;
        Thread ourThread = null;
        boolean isRunning;

        public AnotherSurface(Context context) {
            // TODO Auto-generated constructor stub
            super(context); //not auto-generated; set it up manually
            isRunning = false;
            ourHolder = getHolder();    
        }

        public void ourPause(){
            isRunning = false;
            while(true){
                try {
                    ourThread.join();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            }
            ourThread = null;
        }

        public void ourResume(){
            isRunning = true;
            ourThread = new Thread(this);
            ourThread.start();
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true){
                if(!ourHolder.getSurface().isValid())
                    continue;

                Canvas canvas = ourHolder.lockCanvas();
                canvas.drawRGB(255, 0, 0);
                if(x!=0 && y!=0){
                    Bitmap ourBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.green_ball);
                    canvas.drawBitmap(ourBitmap, x-(ourBitmap.getWidth()/2), y-(ourBitmap.getHeight()/2), null);
                }
                ourHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

现在,当我启动活动时,它按需要工作,它会在点击屏幕的位置创建一个位图(以点击为中心)。它给出的问题是,当我按下手机上的后退键时,应用程序停止响应,手机会提供强制关闭应用程序的选项。我认为它必须对“ourThread”线程没有正确连接做一些事情。

知道问题出在哪里?谢谢。

<小时/> 编辑:我确实找到了我错的地方。在while循环中:

while(true){
        if(!ourHolder.getSurface().isValid())
            continue;

        Canvas canvas = ourHolder.lockCanvas();
        canvas.drawRGB(255, 0, 0);
        if(x!=0 && y!=0){
            Bitmap ourBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.green_ball);
            canvas.drawBitmap(ourBitmap, x-(ourBitmap.getWidth()/2), y-(ourBitmap.getHeight()/2), null);
        }

我刚刚将“true”改为“isRunning”。现在线程结束,因此,按下后退按钮时活动关闭。感谢所有宝贵的建议。

1 个答案:

答案 0 :(得分:2)

  

问题在于,“ourThread”在加入时永远不会停止。

你必须意识到调用ourThread.join()只有等待才能完成线程 - 它不会停止线程。由于某种原因,您的ourThread可能会被挂起。线程转储将显示它正在运行的位置。也许它陷入了循环?也许它正在等待网络连接?

如果join()成功返回,则根据定义,已加入的线程不再运行。所以调用ourThread.join()的线程将等到ourThread线程完成。

如果线程不再运行,那么可能还有其他线程正在运行以保持应用程序打开? thread dump会显示other non-daemon threads仍然存在的内容。他们需要在您的申请停止之前终止。

在查看你的线程代码时,除非抛出RuntimeException,否则我看不到任何退出无限循环的方法。线程什么时候停止工作?您的意思是break;代替continue;吗?

while(true){
    if(!ourHolder.getSurface().isValid())
        continue; // should this be a break?
    Canvas canvas = ourHolder.lockCanvas();
    canvas.drawRGB(255, 0, 0);
    ourHolder.unlockCanvasAndPost(canvas);
}

现在您已添加了更多代码,您需要将isRunning设为volatile,以便多个线程可以更新它并查看更新,您应该更改while循环您的run()方法是:

private volatile boolean isRunning;
...
while(!isRunning){