Когда бы вы вызывали java thread.run () вместо thread.start ()?

109

Когда бы вы назвали Java thread.run()вместо thread.start()?

пустой
источник
47
Когда я использую метод thread.start ()? :)
Bill the Lizard
3
@blank, Ответ прост: t.run()когда вы хотите запустить tзадачу в текущем потоке, и t.start()когда вы хотите запустить tзадачу в tсамом потоке . Или вы спрашиваете о реальных случаях использования?
Pacerier
2
Когда вы идиот и хотите потратить час на отладку многопоточного кода, чтобы потом понять, что вам нужно было просто позвонить start()! Как и я ... Этот метод не должен быть публичным!
Пьер Анри,
См. Также stackoverflow.com/questions/2674174/…
Radiodef

Ответы:

113

Вы можете вызвать run () в конкретном модульном тесте, который касается строго функциональности, а не параллелизма.

Пол Кроаркин
источник
95

Никогда. Вызов run () напрямую просто выполняет код синхронно (в том же потоке), как и при обычном вызове метода.

Адам Крум
источник
25
«Никогда» слишком уж безоговорочно. Может быть, не всегда нужен новый поток, и все равно выполнять код?
Tomalak
4
Возможно, но в этом случае было бы излишне расточительно создавать новый поток только для вызова метода run (). Лучше создать Runnable impl и либо запустить его в потоке, либо построить и запустить с ним новый поток.
Скотт Бэйл
1
Просто повторюсь ... если никогда, то почему метод общедоступен?
пусто,
4
Это общедоступно, потому что Thread реализует Runnable. Вы можете создать подкласс Thread и переопределить run (), что имеет тот же эффект, что и размещение вашего кода в Runnable и передача его в конструктор Thread. Однако лучше использовать отдельный объект Runnable, поскольку это дает вам больше гибкости (например, передача его Executor и т. Д.).
Adam Crume
2
Позвольте мне привести конкретный пример, с которым я сейчас работаю: у меня есть программа, которую можно запускать как через графический интерфейс, так и из командной строки. В случае с графическим интерфейсом я хочу, чтобы объект, который выполняет тяжелую работу, запускался в отдельном потоке и отправлял обновления графическому интерфейсу. В режиме командной строки мне не нужен этот отдельный поток.
Эдвард Фальк
27

Взято из FAQ по потокам Java в стиле кода :

В: В чем разница между методами start () и run () потока?

О: Отдельные методы start () и run () в классе Thread предоставляют два способа создания многопоточных программ. Метод start () запускает выполнение нового потока и вызывает метод run (). Метод start () немедленно возвращается, и новый поток обычно продолжается до тех пор, пока метод run () не вернется.

Метод run () класса Thread ничего не делает, поэтому подклассы должны переопределить метод кодом для выполнения во втором потоке. Если поток создается с аргументом Runnable, метод потока run () вместо этого выполняет метод run () объекта Runnable в новом потоке.

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

Томалак
источник
thread's run() method executes the run() method of the Runnable object in the new thread instead.Это неправда (или, по крайней мере, мой исходный код Java 8 говорит об обратном), но, к сожалению, ссылка не работает, поэтому я сообщаю об ошибке здесь.
kajacx
1
@Tomalak, это не отвечает на заданный вопрос. Вопрос не в разнице, а в вариантах использования, когда мы будем звонить thread.run()вместо thread.start().
Pacerier
24

Выполнение thread.run()не создает нового, Threadв котором выполняется ваш код. Он просто выполняет код в текущем потоке, из которого этот thread.run()код вызывается.

Выполнение thread.start()создает новый поток уровня ОС, в котором вызывается run()метод.

По сути:

Однопотоковое программирование → Непосредственный вызов run()метода

Многопоточное программирование → Вызов start()метода

Более того, как отмечали другие, «тестирование», по-видимому, является единственным рекомендуемым случаем, когда вы можете вызывать run()непосредственно из своего кода.

Махендра Лия
источник
13

Об этом уже упоминалось, но для ясности: создание нового объекта Thread только для вызова его метода run () излишне дорого и должно быть серьезным красным флажком. Было бы намного лучше, с большей развязкой создать Runnable impl и либо (а) вызвать его метод run () напрямую, если это желаемое поведение, либо (b) создать новый поток с этим Runnable и запустить поток.

А еще лучше, для еще большей развязки, ознакомьтесь с Executorинтерфейсом и фреймворком в JDK 5 и новее. Это позволяет вам, в двух словах, отделить выполнение задачи (экземпляр Runnable) от того, как она выполняется (реализация Executor, которая может выполнять Runnable в текущем потоке, в новом потоке, используя существующий поток из пула, и что "нет).

Скотт Бэйл
источник
9

Звоните thread.start(), он в свою очередь позвонит thread.run(). Не могу придумать случая, когда вы хотели бы обойти thread.start()и перейти прямо кthread.run()

Крис Балланс
источник
3
Во время тестирования это единственный законный случай, о котором я могу думать. В противном случае содержимое run () должно быть в отдельном методе, который вызывается запуском или другими способами.
Bill the Lizard
9

Отдельные start()и run()методы в классе Thread обеспечивают два способа создания многопоточных программ. start()Метод начинает выполнение нового потока и вызывает run()метод. start()Метод возвращает немедленно и новый поток обычно продолжается до run()возврата метода.

Метод класса Thread run()ничего не делает, поэтому подклассы должны переопределить метод кодом для выполнения во втором потоке. Если поток создается с аргументом Runnable, run()метод run()потока вместо этого выполняет метод объекта Runnable в новом потоке.

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

ссылка

Alok
источник
То же, что и ответ Tomalak !! Если вы ссылались на какое-то место, укажите это !!
Барри
The start() method returns immediately and the new thread normally continues until the run() method returns.Если start()немедленно возвращается, почему он run()продолжает работать, учитывая, что он был назван сам по себеstart()
KNU
7

Если вопрос был - «почему вызывается метод запуска потока, а не метод запуска напрямую», то я ответил приведенным ниже примером кода. Надеюсь, что это прояснит. В примере ниже:

/*
By calling t1.start(), 
we are getting the main calling thread returned immediately 
after the t1.start() called and is ready to proceed for other 
operations.And the thread t1 starts executing the run method of the object r. 
Hence the the output will be:

      I am the main thread , i created thread t1 and had it execute run method, which is currently looping from 0 to 1000000

      I am done executing run method of testThread

*/


/* If we call t1.run() instead of t1.start(), (just replace t1.start() with t1.run() in the code for testing)
 its like a regular method call and the main thread will not return until the run method completes, 
 hence the output will be:

         I am done executing run method of testThread

         I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000

*/


class testThread implements Runnable{

 public void run()
 {
     for(int i=0;i<1000000;i++){} //a simple delay block to clarify.

     System.out.println("I am done executing run method of testThread");

 }  
}

public class mainClass{

   public static void main(String [] args)
    {
          testThread r = new testThread();
          Thread t1 = new Thread(r);
          t1.start();  /* Question is: can we call instead t1.run() */  
          System.out.println("I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000");

    }
}
Steer360
источник
5

Когда вы хотите, чтобы он работал синхронно. Вызов метода run на самом деле не даст вам многопоточности. Метод запуска создает новый поток, который вызывает метод запуска.

Брайан
источник
3

Если вы хотите выполнить содержимое run (), как и любой другой метод. Конечно, не для того, чтобы начинать нить.


источник
3

Предполагая, что вы знаете, как используются методы запуска и запуска, т.е. синхронный или асинхронный; Метод run можно использовать только для проверки работоспособности.

Кроме того, в некоторых случаях один и тот же класс потока может использоваться в двух разных местах с требованиями к синхронизирующей и асинхронной функциональности, имея два разных объекта с вызовом одного метода запуска и другого метода запуска.

Салман Касбати
источник
2

По крайней мере, в JVM 1.6 есть некоторая проверка и запуск, вызываемый изначально:

 public synchronized void start() {
        /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added 
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
        stop0(throwableFromStop);
    }
    }

    private native void start0();
Стив Б.
источник
2

Просто примечание к приведенным выше замечательным комментариям: иногда вы пишете многопоточный код, который использует метод «start» для запуска разных потоков. Вам будет намного проще использовать «run» (вместо «start») для отладки, так как это делает код для синхронного запуска и отладки намного проще.

мсамади
источник
-1
public class TestClass implements Runnable {
    public static void main(String[] args) {
        TestClass tc = new TestClass();

        Thread t1 = new Thread(tc);
        System.out.println("Before Starting Thread " + Thread.currentThread().hashCode());
        t1.start();
        System.out.println("After Starting Thread " + Thread.currentThread().hashCode());
    }

    @Override
    public void run() {
        System.out.println("TestClass Run method is  Running with thread " + Thread.currentThread().hashCode());        
    }
}
Аватар Гираз
источник
Привет, Frnz, проверьте и запустите приведенный выше пример, чтобы четко понять, что первый запуск с t1.start () и хэш-код, а в следующий раз с хеш-кодами t1.run () и chk
Аватар Гираз
Где твой вопрос?
Амен Джлили