Вопрос

My doubt is regarding how to run a piece of code within an API in my service, on another thread.

I have an API func in my service. Only a part of this API's code, which is independent (2-3 LOC), I want to move it to separate thread, as these take up siginificant time, and as these lines of code have no impact on UI thread as of now. This is what I did.

ORIGINAL CODE:

func(){
    subA();
    subB();
    subC();
}

MODIFIED CODE:

Thread mThread = null;
func(){
    subA();
    if(mThread == null){
        mThread = new Thread(){
            public void run(){
                subB();
                subC();
            }
        } 
    }
    mThread.start();
}

On running this code, I am getting an exception for "thread already started".

I did read on SO about this, that an already started thread cannot be re-started again. I need to create a new thread again and start that. But I do not want to create a new thread object everytime, as that will lead to performance issues on UI thread. Is there any other way this can be handled.

I discovered a couple of other ways to acheive this in android, like Handler, HandlerThread, AsyncTask, etc. But I am not able to settle my mind on which is the best to use here (I do not want to create new objects everytime (of thread/asynctask/handler/handlerthread), just wan to create thread object once and re-use it everytime).

If anybody has worked on this area before, please help !

Это было полезно?

Решение

On further looking into thread part, I managed to find that using ThreadHandler is simpler than using a thread + a looper (as a ThreadHandler has a looper attached to it by default, and manages it well). So, this is the code I am looking towards for now.

HandlerThread mThread = null; 
Handler mHandler = null; 
func(){ 
   subA(); 
    if(mThread == null){
        mThread = new HandlerThread("mThread"); 
        mThread.start();
        mHandler = new Handler(mThread.getLooper());
    } 
    mHandler.post(new Runnable(){
    public void run(){
        subB(); 
        subC();
    }});
}

But I find one issue with this code, I still need to create a new object of a runnable on each call to func(). Need to find out how I can avoid this.

Другие советы

Move the mThread.start(); inside the if(mThread == null) block. You're starting the same thread unconditionally on subsequent calls to the method.

You can only start a thread once, which is why your getting the error.

The simple fix is to use a queue. Have the thread read from the queue in an endless loop, and have other threads put "work" to do into the queue.

Here's an example similar to yours (updated to use blocking interface):

Thread mThread = null;
void func(String dataToWorkWith) {
    final BlockingQueue<String> q = new ArrayBlockingQueue<String>(1000);
    subA();
    q.add("some data if you need it");
    if(mThread == null) {
        mThread = new Thread() {
            public void run() {
                while(true) {
                    try {
                        final String dataToWorkWith = q.take();
                        subB(dataToWorkWith);
                        subC(dataToWorkWith);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        };
        mThread.start();
    }
}

That's assuming you want subA in the main thread each call and subB and subC in a background thread.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top