在单独的线程上运行一段代码

时间:2014-01-30 09:05:44

标签: android multithreading performance android-asynctask android-handler

我怀疑如何在我的服务中的API中运行一段代码,在另一个线程上。

我的服务中有一个API函数。只有这个API的代码的一部分是独立的(2-3 LOC),我想将它移动到单独的线程,因为这些占用了大量的时间,并且因为这些代码行对于现在的UI线程没有影响。这就是我所做的。

原始代码:

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

修改后的代码:

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

在运行此代码时,我收到了“线程已经开始”的例外情况。

我确实读过关于此的内容,已经启动的线程无法重新启动。我需要再次创建一个新线程并启动它。但我不想每次都创建一个新的线程对象,因为这会导致UI线程出现性能问题。有没有其他方法可以处理。

我在Android中发现了另外两种方法来实现这一点,比如Handler,HandlerThread,AsyncTask等。但我无法解决我最好在哪里使用(我不想创建新的)每次(thread/asynctask/handler/handlerthread)的对象,只需创建一次线程对象并每次重复使用它。

如果之前有人在这方面工作过,请帮忙!

3 个答案:

答案 0 :(得分:2)

在进一步研究线程部分时,我设法发现使用ThreadHandler比使用线程+一个looper更简单(因为ThreadHandler默认情况下附加了一个looper,并且管理得很好)。所以,这是我现在正在寻找的代码。

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();
    }});
}

但是我发现这个代码存在一个问题,我仍然需要在每次调用func()时创建一个runnable的新对象。需要了解如何避免这种情况。

答案 1 :(得分:1)

您只能启动一次线程,这就是您收到错误的原因。

简单的解决方法是使用队列。让线程在无限循环中从队列中读取,并让其他线程“工作”进入队列。

以下是与您类似的示例(更新为使用阻止界面):

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();
    }
}

假设你想在每个调用的主线程中使用subA,在后台线程中需要subB和subC。

答案 2 :(得分:1)

mThread.start();移到if(mThread == null)块内。您在后续调用方法时无条件地启动相同的线程。