Подтвердить что ты не робот

Является ли законным вызывать метод запуска дважды в одной теме?

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

updateUI.join();    

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

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

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

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

4b9b3361

Ответ 1

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

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

Далее

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

Итак, да, Thread можно запустить только один раз.

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

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

Ответ 2

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

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

С точки зрения того, что вы можете сделать для повторных вычислений, кажется, что вы можете использовать метод SwingUtilities invokeLater. Вы уже экспериментируете с вызовом run() напрямую, то есть вы уже думаете об использовании Runnable, а не о сыром 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 на ваш расчет, это может быть именно то, что вам нужно.

EDIT: после комментария, я не заметил тег Android в исходном сообщении. Эквивалент invokeLater в работе Android - 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 на соответствующую запись на Handler.

Ответ 3

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

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

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

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

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

Ответ 4

Нет, мы не сможем запускать Thread еще раз, так как это сделает throwtimeException java.lang.IllegalThreadStateException. >

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

Давайте возьмем пример- Думая снова о возобновлении потока и вызывая метод 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
    }

}

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

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

Ответ 5

Что вам нужно сделать, это создать Runnable и обернуть его новым потоком каждый раз, когда вы хотите запустить Runnable. Это было бы очень уродливо, но вы можете обернуть поток другим потоком, чтобы снова запустить код для него, но только это вам действительно нужно.

Ответ 6

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

Прямо от устья лошади: Java API Spec

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

Если вам нужно повторно запустить все, что происходит в вашем потоке, вам нужно будет создать новый поток и запустить его.

Ответ 7

Повторное использование потока является незаконным действием в Java API. Однако вы можете перенести его в runnable-реализацию и снова запустить этот экземпляр.

Ответ 8

Да, мы не можем запустить уже запущенный поток. Он выкинет IllegalThreadStateException во время выполнения - если поток уже запущен.

Что делать, если вам действительно нужно запустить поток: Вариант 1) Если поток нужно запускать более одного раза, тогда нужно создать новый экземпляр Thread и начать с него.

Ответ 9

Можно ли запустить Thread только один раз?

Да. Вы можете запустить его ровно один раз.

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

Не запускайте Thread еще раз. Вместо этого создайте Runnable и опубликуйте его на Handler of HandlerThread. Вы можете отправить несколько объектов Runnable. Если вы хотите отправить данные обратно в поток пользовательского интерфейса, используя метод Runnable run(), введите Message на Handler потока пользовательского интерфейса и процесс handleMessage

Обратитесь к этому сообщению, например, к коду:

Android: тост в потоке

Ответ 10

Было бы очень уродливо делать, но вы можете обернуть поток другим потоком, чтобы снова запустить код для него, но только это вам действительно нужно.

Мне пришлось исправить утечку ресурсов, вызванную программистом, который создал Thread, но вместо того, чтобы запускать его(), он вызвал метод run() - напрямую. Поэтому избегайте этого, если вы действительно не знаете, какие побочные эффекты он вызывает.