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), а это не то, чего я хочу.
Может ли поток быть запущен только один раз? Если да, то что мне делать, если я захочу запустить поток снова? Этот конкретный поток выполняет какие-то вычисления в фоновом режиме, если я не делаю этого в потоке, то это делается в потоке пользовательского интерфейса, и пользователю приходится неоправданно долго ждать.
Никогда не разрешается запускать поток более одного раза. В частности, поток не может быть перезапущен после завершения выполнения.
С точки зрения того, что вы можете сделать для повторных вычислений, кажется, что вы могли бы использовать метод SwingUtilities invokeLater. Вы уже экспериментируете с вызовом run() напрямую, что означает, что вы уже думаете об использовании Runnable, а не raw Thread. Попробуйте использовать invokeLater метод только для Runnable задачи и посмотрите, соответствует ли это вашему ментальному шаблону немного лучше.
Вот пример из документации:
RunnabledoHelloWorld=newRunnable() { publicvoidrun() { // 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()) для нас все равно что просить мертвеца проснуться и бежать. Поскольку после завершения своей жизни человек переходит в мертвое состояние.
/* ВЫВОД в методе run(), метод завершен. Исключение в потоке "основной" java.lang.Исключение IllegalThreadStateException в java.lang.Thread.start(Неизвестный источник) */
Только что полученный ответ объясняет, почему вам не следует делать то, что вы делаете. Вот несколько вариантов решения вашей реальной проблемы.
Этот конкретный поток выполняет какие-то вычисления в фоновом режиме, если я не делаю этого в потоке, то это делается в потоке пользовательского интерфейса, и пользователю приходится неоправданно долго ждать.
Создайте свой собственный поток и используйте AsyncTask.
Или создайте новый поток, когда вам это нужно.
Или настройте свой поток так, чтобы он работал вне рабочей очереди (например, LinkedBlockingQueue), а не перезапускал поток.