Коли ви б назвали java's thread.run () замість thread.start ()?


109

Коли ви б назвали Java thread.run()замість цього thread.start()?


47
Коли я використовую метод thread.start ()? :)
Білл Ящірка

3
@blank, Відповідь проста: t.run()коли ви хочете виконати tзавдання на поточному потоці і t.start()коли ви хочете виконати tзавдання на tсамій потоці . Або ви запитуєте фактичні випадки використання?
Pacerier

2
Коли ви ідіот і хочете витратити годину налагодження багатопотокового коду, щоб пізніше зрозуміти, що ви просто повинні зателефонувати start()! Як я ... Цей метод не повинен бути публічним!
П’єр Генрі

Відповіді:


113

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


95

Ніколи. Виклик run () безпосередньо виконує код синхронно (у тому ж потоці), як і звичайний виклик методу.


25
"Ніколи" - занадто абсолютний. Можливо, не завжди потрібно новий потік і все-таки виконувати код?
Томалак

4
Можливо, але в цьому випадку було б зайвим марно створювати нову Тему лише для виклику методу run (). Краще створити імпульс Runnable і або запустити цей потік або сконструювати і запустити з ним нову нитку.
Скотт Бейл

1
Просто перегляньте… якщо ніколи, чому метод відкритий?
пустий

4
Це загальнодоступне, оскільки Thread реалізує Runnable. Ви можете підкласировать Thread і override run (), що має такий же ефект, як і розміщення коду в Runnable та передача його в конструктор Thread. Однак краще використовувати окремий об’єкт Runnable, оскільки це дає вам більшу гнучкість (наприклад, передача його виконавцю тощо).
Адам Крум

2
Дозвольте навести конкретний приклад, з яким я зараз працюю: у мене є програма, яку можна запускати як GUI, так і з командного рядка. У випадку з графічним інтерфейсом я хочу, щоб об'єкт, який робить важкий підйом, бігав по окремій нитці та надсилав оновлення до gui. У режимі командного рядка мені не потрібен цей окремий потік.
Едвард Фолк

27

Сформований із форм стилю коду Java FAQ :

З: Яка різниця між методами start () і run () потоку?

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

Метод класу Thread 'run () нічого не робить, тому підкласи повинні замінити метод з кодом для виконання у другому потоці. Якщо Thread створено з аргументом Runnable, метод потоку () потоку виконує метод run () об'єкта Runnable в новому потоці.

Залежно від характеру вашої потокової програми, виклик методу run () 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 осущ і або (а) називають це метод Run () безпосередньо , якщо це бажане поведінку, або (б) побудувати нову тему з цим Runnable і почати тему.

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


9

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


3
Під час тестування є єдиним законним випадком, про який я можу придуматись. В іншому випадку вміст run () повинен знаходитися в окремому методі, який викликається запуском, або іншими способами.
Білл Ящірка

9

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

Метод класу Thread ' run()нічого не робить, тому підкласи повинні замінити метод з кодом для виконання у другому потоці. Якщо Нитка інстанціюється аргументом Runnable, run()метод потоку виконує run()метод об’єкта Runnable в новому потоці.

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

довідник


Те саме, що відповідь Томалака !! Якщо ви посилалися з якогось місця, будь ласка, згадайте це !!
Баррі

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");

    }
}

5

Коли ви хочете, щоб він запускався синхронно. Виклик методу запуску насправді не дасть вам багаторівневої нарізки. Метод запуску створює новий потік, який викликає метод запуску.


3

Якщо ви хочете виконати вміст run (), як і будь-який інший метод. Не запускати нитку, звичайно.


3

Якщо припустити, що ви знаєте використання методу запуску та запуску, тобто синхронного проти асинхронного; метод запуску можна використовувати просто для перевірки функціональності.

Крім того, за певних обставин один і той же клас потоку може використовуватися в двох різних місцях з вимогами щодо функцій синхронізації та асинхронізації, якщо два різних об'єкти мають метод запуску та інший спосіб запуску.


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-хеш-
кодами

Де ваше запитання?
Амін Дзілі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.