Android:如何在无限循环内正确管理顺序线程

时间:2011-10-06 01:17:56

标签: android multithreading handler threadpool intentservice

我在IntentService内创建了onHandleIntent无限循环,然后添加静态方法start,resume,pause,stop以直接在我的Activities中调用它。

场景是,在无限循环中,我正在调用回调方法,它正在创建一个新线程来执行长进程。

问题是,我担心由于无限循环而不断创建线程。我很确定有更好的方法来管理它。我在想ThreadPool或者能够以顺序方式只使用一个线程的东西。所以,我节省了时间,内存,开销等。

其他方法非常欢迎。根据需要向我提供其他信息。然后,我会在这里更新。

以下是我的代码(看看SampleCallback):

IntentService

import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class SampleCallbackIntentService extends IntentService {
    private final String LOG_LOGCAT_TAG = "SampleCallbackIntentService";
    private Handler _handler;

    public SampleCallbackIntentService(String name) {
        super(name);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // initialize variables for pause & resume thread
        _mPauseLock = new Object();
        _mPaused = false;
        _mFinished = false;

        // initialize handler to switch to UI/Main thread
         _handler = new Handler()
            {
                @Override
                public void handleMessage(final Message msg)
                {
                    _callback.doSomethingFromUIThread(msg);
                }
            };
    }

    private final SampleCallback _callback = new SampleCallback() {
        @Override
        public void doSomethingFromCurrentThread(final Object object) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //do long running process.
                                    // I will access object here.
                }
            }).start();

        }

        @Override
        public void doSomethingFromUIThread(final Message msg) {
            //may update UI here.
        }
    };

    private final int CALLBACK_MESSAGE = 1;
    @Override
    protected void onHandleIntent(Intent arg0) {
        Log.i(LOG_LOGCAT_TAG, "loop started");
        while (!_mFinished) {
            // do stuff here
            // create the object variable. Then pass to callback method
            _callback.doSomethingFromCurrentThread(object);

            // process and create the result to pass
            String someResult = "some result here";
            _handler.sendMessage(_handler.obtainMessage(CALLBACK_MESSAGE, someResult));

            synchronized (_mPauseLock) {
                while (_mPaused) {
                    try {
                        Log.i(LOG_LOGCAT_TAG, "loop paused");
                        _mPauseLock.wait();
                        Log.i(LOG_LOGCAT_TAG, "loop resumed");
                    } catch (InterruptedException e) {
                        Log.e(LOG_LOGCAT_TAG, "error occured on pause", e);
                    }
                }
            }
            try {
                //using sleep here might be not good design.
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Log.e(LOG_LOGCAT_TAG, "error occured on sleep", e);
            }
        }
        Log.i(LOG_LOGCAT_TAG, "loop ended");
    }

    private static Object _mPauseLock;
    private static boolean _mPaused;
    private static boolean _mFinished;

     public static void start(Context context) {
         Intent service = new Intent(context, SampleCallbackIntentService .class);
         if(context.startService(service)==null) {
             Log.e(LOG_LOGCAT_TAG, "Service cannot be started");
         } else {
             Log.i(LOG_LOGCAT_TAG, "start() called");
         }

     }

    /**
     * Call this on pause.
     */
    public static void pause() {
        Log.i(LOG_LOGCAT_TAG, "pause() called");
        synchronized (_mPauseLock) {
            _mPaused = true;
        }
    }

    /**
     * Call this on resume.
     */
    public static void resume() {
        Log.i(LOG_LOGCAT_TAG, "resume() called");
        synchronized (_mPauseLock) {
            _mPaused = false;
            _mPauseLock.notifyAll();
        }
    }

     public static void stop() {
         if(_mPauseLock == null) return;
         synchronized (_mPauseLock) {
             Log.i(LOG_LOGCAT_TAG, "stop() called");
             _mFinished = true;
         }
     }
}

SampleCallback

import android.os.Message;

public interface SampleCallback {

    public void doSomethingFromCurrentThread(final Object object);

    public void doSomethingFromUIThread(final Message msg);
}

UPDATES1 除了google api,我使用的是位置api。我将创建一个android库项目并使用该api在后台获取最新位置(例如每2秒)。

在应用程序方面,只需要调用静态方法来使用它(例如start(context,callback),pause(),resume(),stop())。它有回调来获取位置。在从location对象获取所需信息后,我将创建一个新线程来调用我自己创建的回调(由应用程序端实现)。

3 个答案:

答案 0 :(得分:2)

您可以使用AsyncTask而不是每次都创建新主题吗? AsyncTask管理固定的线程池(或一个后台线程 - 取决于Android版本),并允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序。

但是我想知道为什么你需要在onHandleIntent方法中创建一个无限循环?通过这样做,您可以阻止IntentService接收更多意图。因为在IntentService中:

  

所有请求都在一个工作线程上处理 - 它们可以作为   只要有必要(并且不会阻止应用程序的主循环),   但一次只能处理一个请求。

我认为你想从IntentService的UI线程中执行一些长时间运行的代码。但这不需要在IntentService工作线程中创建无限循环。只需使用Context.startService(Intent)调用将请求发送到IntentService即可。如果您希望IntentService发回一些结果或只是在UI线程中调用回调,您可以传递Messenger(或ResultReceiver)对象与Intent。

<强>活动

final Handler uiHandler = new Handler(Looper.getMainLooper());

private void postTask() {
  Intent intent = new Intent("com.yourservice.DOACTION");
  intent.putExtra("messenger", new Messenger(handler));
  intent.putExtra("object", YourObject());   // pass other Parcelable objects
  startService(intent);
}

<强> IntentService

protected void onHandleIntent(Intent intent) {
  Messenger messenger = intent.getParcelableExtra("messenger");
  YourObject object = intent.getParcelableExtra("object");

  //... do work here ...

  Message msg = Message.obtain();
  msg.what = CALLBACK_MESSAGE;
  msg.setData(someResult);
  messenger.send(Message.obtain()); 
}

答案 1 :(得分:1)

查看ExecutorService的文档(不要与Android服务混淆)和Executors包。有一些关于如何使用线程池的例子。

答案 2 :(得分:0)

等等,为什么你需要使用所有这些回调?你不能只是让每个意图编码需要做的事情然后让你的onHandleIntent根据意图的信息执行不同的代码。这是IntentService的使用方式。

您不应该在IntentSerivce中执行任何线程处理。 IntentService应该处理所有线程代码(你应该放弃它,因为它可能已经过高度优化)。