Сбой эмулятора Android при использовании параллелизма - PullRequest
1 голос
/ 13 декабря 2010

Этот вопрос касается использования Google Android SDK на языке программирования Java.

Мой вопрос можно свести к следующему: Почему этот код вызывает аварийный запуск эмулятора Android?

В течение нескольких дней я боролся с параллелизмом, связанным с настройкой различных потоков для игрового приложения.Я сделал много вариаций, но все они провалились.На данный момент, я просто хочу запустить базовую параллельную настройку.Хуже всего то, что происходит сбой эмулятора, поэтому DDMS ничего не сообщает;поэтому я совершенно не знаю, где проблема.

Следующий код показывает действие (класс Main), которое вызывает класс SceneManager, который создает поток, который будет использоваться для игровой логики.Третий класс, StatusChannel, используется (будет) для передачи информации о состоянии между различными потоками (в конечном итоге также будет создан поток визуализации OpenGL).

Эмулятор аварийно завершает свою работу в разное время.Он может работать в течение 20 секунд или 5 минут.

setContentView (R.layout.main) в классе Activity - это просто базовая компоновка, которую создает Eclipse.

Я прокомментировалиспользование Node (созданного в классе Activity и доступного в SceneManager)

Я установил SDK версий от 1,5 до 2,3 - текущее приложение ориентировано на 2,1

Проблема имеет что-то делатьс классом SceneManager.Я особенно подозрительно отношусь к методу run ().

Вот 3 класса.

Извините за длину кода.

public class Main extends Activity {
 private SceneManager mSceneManager;
 private volatile Node mSceneGraph = new Node(); 
 private volatile Status mStatusChannel = new Status();

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
     Log.d("-- Main", "onCreate()");
        super.onCreate(savedInstanceState);     

        setContentView(R.layout.main);

        // Holds the scene assets, such as the stage,
        // the agents, camera, etc.
        mSceneManager = new SceneManager(mSceneGraph, mStatusChannel);      
        mSceneManager.onCreate();
    }

    @Override
    protected void onResume() {
     Log.d("-- Main", "onResume()");     
        super.onResume();
     mSceneManager.onResume();                 
    }     

    @Override
    protected void onPause() {
     Log.d("-- Main", "onPause()");     
        super.onPause();
        mSceneManager.onPause();        
    }  

    @Override
    protected void onDestroy() {
     Log.d("-- Main", "onDestroy()");
        super.onDestroy();
        mSceneManager.onDestroy();
    }    
}




public class SceneManager implements Runnable{
 private Thread mThread;
 private volatile Status mStatusChannel;
 private volatile Node mSceneGraph;

 private volatile long mMillis = 0; 
 private volatile PrepareVisitor mPrepareVisitor;
 private volatile int mStatus = Status.UNKNOWN_STATUS; 

 SceneManager(Node sceneGraph, Status statusChannel) {
  mPrepareVisitor = new PrepareVisitor();
  mStatusChannel = statusChannel;
  mSceneGraph = sceneGraph;
        mMillis = SystemClock.uptimeMillis();  
  mThread  = new Thread(this); 
  mThread.setName("LogicThread"); 
  mStatusChannel.setSceneManagerStatus(Status.READY_STATUS);
 }

 public void onCreate() {
  Log.d("-- SceneManager", "onCreate()..."); 
  // This will start the thread in a paused state.
  mThread.start(); 
 }

 public void onResume() {
  Log.d("-- SceneManager", "onResume()...");

  // Unpause the status manager, if it is currently paused.
  if (mStatusChannel.getSceneManagerStatus() == Status.PAUSED_STATUS) {
   mStatusChannel.setSceneManagerStatus(Status.READY_STATUS);  
  }  
 } 

 public void onPause() {
  Log.d("-- SceneManager", "onPause()...");   
  if (mStatusChannel.getSceneManagerStatus() != Status.UNKNOWN_STATUS) {
   mStatusChannel.setSceneManagerStatus(Status.PAUSED_STATUS);  
  }
 } 

 public void onDestroy() {  
  mStatusChannel.setSceneManagerStatus(Status.QUIT_STATUS);  
  try {
   mThread.join();
  }
  catch (InterruptedException e) {
   Log.d("-- SceneManager", "InterruptedException");
  }
 }

 /**
  *  This method should not be called by clients of this class.
  */
 @Override
 public void run() {
  Log.d("-- SceneManager", "Called...");

  // Main logic loop.
  outer: while (true) {

   // How much time has elapsed since last call.
   long timeDelta = SystemClock.uptimeMillis() - mMillis; 

   switch (mStatus) {
   case Status.READY_STATUS:
    //mPrepareVisitor.go(mSceneGraph, timeDelta);
    break;   
   case Status.PAUSED_STATUS:
    break;
   case Status.QUIT_STATUS:
    break outer;    
   case Status.UNKNOWN_STATUS:
    int renderStatus = mStatusChannel.getRendererStatus();    
    if (renderStatus == Status.READY_STATUS) {
     mStatusChannel.setSceneManagerStatus(Status.READY_STATUS);
    }
    break;
   }

   mStatus = mStatusChannel.getSceneManagerStatus();

         // Update the time.
   mMillis = SystemClock.uptimeMillis(); 
  }
 } 
}


public class Status {

 /* Generic Statuses */
 public final static int UNKNOWN_STATUS = 0; 
 public final static int READY_STATUS = 1;  
 public final static int PAUSED_STATUS = 2;  
 public final static int QUIT_STATUS = 3;  

 /* Current statuses values */
 private int mSceneManagerStatus = UNKNOWN_STATUS ;
 private int mRendererStatus  = UNKNOWN_STATUS ;


 public synchronized int getSceneManagerStatus() {
  return mSceneManagerStatus;
 }

 public synchronized int getRendererStatus() {
  return mRendererStatus;
 }

 public synchronized void setSceneManagerStatus(int status) {
  mSceneManagerStatus = status;
 }

 public synchronized void setRendererStatus(int status) {
  mRendererStatus = status;
 } 
}

- EDIT -

This issue happens even with something as simple as this:

public class ThreadActivity extends Activity {
    private Booboo mBooboo;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mBooboo = new Booboo();
        mBooboo.onCreate();
    }
}

public class Booboo implements Runnable {
        private Thread mThread;

        Booboo() {
                mThread = new Thread(this, "SceneManagerThread");       
        }

        public void onCreate() {
                Log.d("Booboo", "Thread started");
                mThread.start();
        }

        @Override
        public void run() {
                while (true) {}
        }
}

Я знаю, первая реакция - сказать, что это время (правда) {}.Просто помните, что это надуманный пример, чтобы показать проблему.В своем собственном коде я выполняю действия в течение жизненного цикла, как описано в документации.Проблема в том, что эмулятор падает через некоторое время в таком бесконечном цикле, независимо от того, есть ли у вас условия прерывания или нет.

1 Ответ

0 голосов
/ 17 июня 2011

Вы, вероятно, хотите заглянуть в AsyncTask.Здесь есть отличная статья: http://android -developers.blogspot.com / 2009/05 / painless-threading.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...