我需要在我的应用中多次调用同一个线程。使用我的原始代码,第一次可以执行得很好。但第二次崩溃 - 然后我才知道每个线程只能执行不超过一次。
我的原始代码:
View.OnClickListener myClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
mythread.start();
}
};
Thread mythread = new Thread(){
@Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
正如我所说,如果我第二次尝试运行它会崩溃。所以我尝试修改它:
View.OnClickListener myClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
test();
}
};
private void test(){
Thread mythread = new Thread(){
@Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
mythread.start();
}
效果很好;但我的问题是,这是否是执行此操作的正确方法,还是有更优化的方法来执行此操作?
另外,从另一个线程的内部调用线程是否可以接受? (就像我把东西放在我的新线程中的UI Thread上的方式)
编辑: 这只是一个例子。对于我的实际代码,我需要进行大量基于数学的模拟,需要10秒才能完成。根据将向用户显示的结果,他们可能希望更改其输入参数并让模拟再次运行。这将发生好几次。
答案 0 :(得分:4)
除了使用AsyncTask或runOnUiThread()的其他好答案之外,您还可以将私有成员定义为Runnable,如下所示:
private Runnable mytask = new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
然后,无论何时想要运行它,都要执行
new Thread(mytask).start();
答案 1 :(得分:2)
没有什么不好,但我认为更好的方法是使用AsyncTask。它完全是为这种情况而设计的。
您可以多次使用AsyncTask
,只需创建一个新的new MyAsyncTask().execute("");
{来自here)
答案 2 :(得分:0)
另外,从另一个线程的内部调用线程是否可以接受? (就像我把东西放在我的新线程中的UI Thread上的方式)
runOnUiThread
仅用于此目的。但通常有更好的方法(例如AsyncTask
),所以使用这种方法可能是一个坏主意。
我的问题是,这是否是执行此操作的正确方法,还是有更优化的方法来执行此操作?
您不应仅仅使用线程来安排未来的任务。它们对于与主线程并行执行某些操作非常有用,但会增加许多潜在的错误(尝试在它之间旋转屏幕打印running..finished,可能会崩溃)
我会在你的情况下使用CountDownTimer
。
或Handler
例如在这里:Schedule task in android
答案 3 :(得分:0)
从提供的代码中我假设您想要在长时间的数学计算之前和之后执行UI操作。在诸如@Andres建议的情况下,AsyncTask是您的最佳选择。它提供onPreExecute方法,onPostExecute,它在UI线程上运行,因此不需要显式调用runOnUiThread。
关键概念:
您无法启动已启动的主题。这将返回IllegalStateException。如果需要再次执行相同的任务,则应创建一个新实例。
如果您发现自己创建了多个线程实例(甚至是AsyncTask),因为您需要反复运行相同的任务,我建议您使用线程池或简单的Java Executor服务。创建一个singleThread或者可以是pool并将你的runnable发布到executorService上,它将负责其余部分。
线程间或进程间通信是非常常见的要求。