Android

Is it legal to call the start method twice on the same Thread?

Законно ли вызывать метод start дважды в одном и том же потоке?

Следующий код приводит к тому, java.lang.IllegalThreadStateException: Thread already started что я вызвал start() метод во второй раз в программе.

updateUI.join();    

if (!updateUI.isAlive())
updateUI.start();

Это происходит при вызове второго раза updateUI.start(). Я прошел через это несколько раз, и поток вызывается и полностью выполняется до завершения, прежде чем нажать updateUI.start().

Вызов updateUI.run() позволяет избежать ошибки, но заставляет поток выполняться в потоке пользовательского интерфейса (вызывающем потоке, как упоминалось в других сообщениях на SO), а это не то, чего я хочу.

Может ли поток быть запущен только один раз? Если да, то что мне делать, если я захочу запустить поток снова? Этот конкретный поток выполняет какие-то вычисления в фоновом режиме, если я не делаю этого в потоке, то это делается в потоке пользовательского интерфейса, и пользователю приходится неоправданно долго ждать.

Переведено автоматически
Ответ 1

Из спецификации Java API для Thread.start метода:


Никогда не разрешается запускать поток более одного раза. В частности, поток не может быть перезапущен после завершения выполнения.


Кроме того:


Выдает:

IllegalThreadStateException - если поток уже был запущен.


Итак, a Thread может быть запущен только один раз.


Если да, то что мне делать, если я захочу запустить поток снова?


Если Thread необходимо запустить более одного раза, то следует создать новый экземпляр Thread и вызвать start для него.

Ответ 2

Совершенно верно. Из документации:


Никогда не разрешается запускать поток более одного раза. В частности, поток не может быть перезапущен после завершения выполнения.


С точки зрения того, что вы можете сделать для повторных вычислений, кажется, что вы могли бы использовать метод SwingUtilities invokeLater. Вы уже экспериментируете с вызовом run() напрямую, что означает, что вы уже думаете об использовании Runnable, а не raw Thread. Попробуйте использовать invokeLater метод только для Runnable задачи и посмотрите, соответствует ли это вашему ментальному шаблону немного лучше.

Вот пример из документации:

 Runnable doHelloWorld = new Runnable() {
public void run() {
// Put your UI update computations in here.
// BTW - remember to restrict Swing calls to the AWT Event thread.
System.out.println("Hello World on " + Thread.currentThread());
}
};

SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");

Если вы замените этот println вызов своим вычислением, это может быть именно то, что вам нужно.

РЕДАКТИРОВАТЬ: следуя комментарию, я не заметил тег Android в исходном сообщении. Эквивалент invokeLater в Android work - Handler.post(Runnable). Из его javadoc:

/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/

Итак, в мире Android вы можете использовать тот же пример, что и выше, заменив Swingutilities.invokeLater соответствующим post на a Handler.

Ответ 3

Нет, мы не можем запустить поток снова, это вызовет исключение RuntimeException java.lang.Исключение IllegalThreadStateException . >


Причина в том, что как только метод run() выполняется потоком, он переходит в нерабочее состояние.


Давайте возьмем пример - думать о повторном запуске потока и вызывать в нем метод start() (который внутренне собирается вызвать метод run()) для нас все равно что просить мертвеца проснуться и бежать. Поскольку после завершения своей жизни человек переходит в мертвое состояние.

public class MyClass implements Runnable{

@Override
public void run() {
System.out.println("in run() method, method completed.");
}

public static void main(String[] args) {
MyClass obj=new MyClass();
Thread thread1=new Thread(obj,"Thread-1");
thread1.start();
thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
}

}

/* ВЫВОД в методе run(), метод завершен. Исключение в потоке
"основной" java.lang.Исключение IllegalThreadStateException
в java.lang.Thread.start(Неизвестный источник)
*/


проверьте это

Ответ 4

Только что полученный ответ объясняет, почему вам не следует делать то, что вы делаете. Вот несколько вариантов решения вашей реальной проблемы.


Этот конкретный поток выполняет какие-то вычисления в фоновом режиме, если я не делаю этого в потоке, то это делается в потоке пользовательского интерфейса, и пользователю приходится неоправданно долго ждать.


Создайте свой собственный поток и используйте AsyncTask.

Или создайте новый поток, когда вам это нужно.

Или настройте свой поток так, чтобы он работал вне рабочей очереди (например, LinkedBlockingQueue), а не перезапускал поток.

2023-11-13 11:56 java android multithreading