我怀疑如何在我的服务中的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
)的对象,只需创建一次线程对象并每次重复使用它。
如果之前有人在这方面工作过,请帮忙!
答案 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)
块内。您在后续调用方法时无条件地启动相同的线程。