마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

스레드 종료에 대해서.. 질문입니다..

0 추천

가입 첫글부터.. 질문이라.. 정말 죄송합니다...

많은 것을 배워서 저도 질문에 답변하는 회원이 되도록 해야겠어요 !!!

 

다름이 아니라 쓰레드가 종료가 안되는 것(비정상)으로 되는것 같아 질문합니다...

 

thread.join();을 통해서 종료하는 것으로 알고 있는데.. 자꾸 종료가 되어버리네요....

원소스


package com.example.controlpannel;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.WindowManager;

public class GameView extends SurfaceView implements Callback {
	private String tag;

	private Context mContext;
	private SurfaceHolder mHolder;
	private GameThread mThread;

	private int width, height, cx, cy;
	private int x1, y1, x2, y2;
	private int sx1, sy1, sx2, sy2;
	private Rect src, dst;
	private Bitmap imgBack;
	private Bitmap User;
	private int w, h;
	private long counter = 0;
	private boolean canRun = true;

	public GameView(Context context, AttributeSet attrs) {
		// TODO Auto-generated constructor stub
		super(context, attrs);
		SurfaceHolder holder = getHolder();
		holder.addCallback(this);
		mHolder = holder;
		mContext = context;
		mThread = new GameThread();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		mThread.start();
		Log.d(tag, "THREAD START");
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		
		boolean done = true;
		while (done) {
			
			try {
				//mThread.stop();
				mThread.join();
				
				Log.d(tag, "THREAD END");
				done = false;
				
			} catch (InterruptedException e) {
				
				//e.printStackTrace();
			}
		}
	}

	class GameThread extends Thread {
		public GameThread() {
			Display display = ((WindowManager) mContext
					.getSystemService(mContext.WINDOW_SERVICE))
					.getDefaultDisplay();
			width = display.getWidth();
			height = display.getHeight();

			cx = width / 2;
			cy = height / 2;
			Resources res = mContext.getResources();

			imgBack = BitmapFactory.decodeResource(res, R.drawable.map);
			imgBack = Bitmap.createScaledBitmap(imgBack, width * 2, height * 2,
					true);

			User = BitmapFactory.decodeResource(res, R.drawable.user);
			w = User.getWidth() / 2;
			h = User.getHeight() / 2;

			dst = new Rect(0, 0, width, height);
			src = new Rect();

			x1 = imgBack.getWidth() - width;
			y1 = imgBack.getHeight() - height;
			sx1 = -1;
			sy1 = -1;
		}

		public void run() {
			Canvas canvas = null;
			while (canRun == true) {
				canvas = mHolder.lockCanvas();
				try {
					synchronized (mHolder) {
						ScrollViewport();
						canvas.drawBitmap(imgBack, src, dst, null);
						canvas.drawBitmap(User, cx - w, cy - h, null);
					}
				}
					catch(NullPointerException e){
					
					
					}
				 finally {
					mHolder.unlockCanvasAndPost(canvas);
				}
			}
			
		}
		

		private void ScrollViewport() {
			counter++;
			if (counter % 2 == 0) {
				x1 += sx1;
				y1 += sy1;
				if (x1 < 0)
					x1 = imgBack.getWidth() - width;
				if (y1 < 0)
					y1 = imgBack.getHeight() - height;
				src.set(x1, y1, x1 + width, y1 + height);
			}
		}
	}
}

 

로그는

07-31 22:30:44.716: E/SpannableStringBuilder(24275): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
07-31 22:30:44.716: E/SpannableStringBuilder(24275): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
07-31 22:30:44.841: W/dalvikvm(24275): threadid=11: thread exiting with uncaught exception (group=0x411e0930)
07-31 22:30:44.846: E/AndroidRuntime(24275): FATAL EXCEPTION: Thread-17022
07-31 22:30:44.846: E/AndroidRuntime(24275): java.lang.IllegalArgumentException
07-31 22:30:44.846: E/AndroidRuntime(24275): at android.view.Surface.nativeUnlockCanvasAndPost(Native Method)
07-31 22:30:44.846: E/AndroidRuntime(24275): at android.view.Surface.unlockCanvasAndPost(Surface.java:466)
07-31 22:30:44.846: E/AndroidRuntime(24275): at android.view.SurfaceView$4.unlockCanvasAndPost(SurfaceView.java:851)
07-31 22:30:44.846: E/AndroidRuntime(24275): at com.example.controlpannel.GameView$GameThread.run(GameView.java:126)
 
이렇게 나오네요....
휴.. 뭐가 잘못인건지...어렵네요!!
따라멋쟁이 (250 포인트) 님이 2013년 7월 31일 질문

2개의 답변

0 추천
 
채택된 답변
GameView.java:126 에 문제가 있는가보네요ㅎ

쓰레드같은 경우는 바로 종료하기가 힘들어서 쓰레드를 연속으로 쓰는건 좋지않을거에요.

특히나 쓰레드 종료메서드인 join이나 intterrupt는 종료를 요청하겠다는거지, 종료시킨다는말이 아니거든요.

join이나 intterrupt를 호출해도 조금 지난뒤에 멈출거에요.

 

join같은 경우는 끝날때까지 기다렸다가 다음 쓰레드나 메서드를 진행하겠다는 의미로쓰는거구요.

그냥 종료할려면 interrupt를 써보세요.

 

특히나 쓰레드를 객체로 만들어놓고 멈췄다가 실행했다가 하면 자주 뻑나더라구요.

어짜피 쓰레드 종료요청하거나 소스가 끝나면 알아서 종료되니깐 즉석에서 new로 생성해서 실행하는게 쓰레드 익셉션피하는 방법중에 하나일듯요ㅎ
기초개발자 (24,060 포인트) 님이 2013년 8월 1일 답변
따라멋쟁이님이 2013년 8월 1일 채택됨
감사합니다 !! 제가 개념을 잘못 이해했군요 !! 감사합니다 !!
0 추천
join은 스레드 종료를 기다린다는 것이지 스레드를 종료시키는게 아닙니다.
(종료 요청도 안보내고 마냥 기다립니다.)
익명사용자 님이 2013년 8월 1일 답변
감사합니다 !! 제가 개념을 잘못 이해했군요 !! 감사합니다 !!
...