我有一个onClick()
方法,里面有Thread
。简化的结构如下。
imageA = (ImageView) findViewById(R.id.imageA);
imageA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {myThread.start();}
});
Thread myThread = new Thread() {
@Override
public void run() {
// some stuff here
}
};
再次单击,我收到以下错误:
Thread already started
我在一些论坛中读到,不止一次启动Thread
不是一个好主意而且使用它是不够的:
if (!myThread.isAlive()){myThread.start();}
建议的选项是创建新的Thread
。问题是重复使用相同的Thread
对我来说更舒服。所以问题是:
Thread
?由于
答案 0 :(得分:2)
不止一次启动线程永远不合法。特别是,一旦完成执行,线程可能无法重新启动。
答案 1 :(得分:1)
线程实例不能使用两次。
如果您想将相同的Thread
重用于一系列任务,则应在Looper
中使用Thread
。
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
另一种直接使用的替代方法是使用HandlerThread
class MyHandlerThread extends HandlerThread {
Handler handler;
public MyHandlerThread(String name) {
super(name);
}
@Override
protected void onLooperPrepared() {
handler = new Handler(getLooper()) {
@Override
public void handleMessage(Message msg) {
// process incoming messages here
// this will run in non-ui/background thread
}
};
}
}
然后您可以通过传递消息来完成任务
//Create and send a new message to looper
fun sendMessage(messageToSend: String?) {
//Create and post a new message to handler
if (messageToSend != null && handler != null) {
val encodeMessage = encodeMessage(messageToSend)
handler!!.sendMessage(encodeMessage)
} else {
Log.e(TAG, "Looper is not prepared or message is Null")
sendResultToUI("Looper is not prepared or message is Null")
}
}
private fun encodeMessage(messageToSend: String): Message {
val message = Message()
val bundle = Bundle()
bundle.putString(BUNDLE_KEY, messageToSend)
message.data = bundle
return message
}
答案 2 :(得分:0)
在Thread ore对象上调用start方法将导致异常。如果您需要重用该线程,那么一旦完成其操作,您需要让它等待锁定。当您需要重用它时,您需要通知它唤醒。这可以在一个对象的帮助下,让它调用它锁定,一旦完成任务,你需要在synchronized块内调用lock.wait()(在锁定时同步)。当你再次需要它时,你只需在synchronized块中调用lock.notify()agin(在锁定时同步)。
通过使用Java并发包提供的Threadpool,可以避免上述复杂性。 Threadpool是一个线程对象池。它处理将任务分配给free(或新的,根据chosed threadpool)线程的复杂性,并在执行分配的工作后将对象返回到自由线程对象池。当新任务到来时,pool会将任务分配给其中一个免费线程。
答案 3 :(得分:0)
如果要重用线程,请使用具有大小为1的线程池的ExecutorService,或者您希望拥有多少线程,执行程序将重用它们。
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(() -> {
});