Яка різниця між запуском теми () та запуском ()


224

Скажіть, у нас є ці два Runnables:

class R1 implements Runnable {
    public void run() {  }
    
}

class R2 implements Runnable {
    public void run() {  }
    
}

Тоді яка різниця між цим:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();

    r1.run();
    r2.run();
}

І це:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();
}

Відповіді:


309

Перший приклад: Немає декількох потоків. Обидва виконують в одному (існуючому) потоці. Немає створення ниток.

R1 r1 = new R1();
R2 r2 = new R2();

r1і r2є лише двома різними об'єктами класів, які реалізують Runnableінтерфейс і таким чином реалізують run()метод. Коли ви телефонуєте, r1.run()ви виконуєте його в поточному потоці.

Другий приклад: дві окремі нитки.

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1і t2є об'єктами класу Thread. Коли ви зателефонуєте t1.start(), він запускає новий потік і викликає внутрішній run()метод, r1щоб виконати його всередині цього нового потоку.


5
Could Я вважаю, що перед тим, як викликати Thread # start (), нічого насправді відносно потоку OS не відбувається? Це лише об'єкт java.
Жаске

4
Це правильно згідно документації. Перевірте код ініціалізації потокового об'єкта, який відповідає документації. Також у вихідному коді - це те start(), що викликає метод natvie, який повинен викликати те, що пов'язано з потоком os.
Bhesh Gurung

3
Документи конструктора ниток тут . Тут знаходиться джерело ініціалізації теми . тутstart() джерело методу .
Bhesh Gurung

92

Якщо ви просто викликаєте run()безпосередньо, він виконується на виклику потоку, як і будь-який інший метод виклику. Thread.start()Потрібно фактично створити нову нитку, щоб runметод виконання виконувався паралельно.


2
У Hotspot JVM існує пряме відображення між Java-ниткою та нативною ниткою. Thread.start()покликання робить стан нитки перехід від нового стану в Runnable стану. Виконання не означає, що нитка запущена. Після ініціалізації нативного потоку нативний потік викликає run()метод у потоці Java, завдяки чому стан потоку змінюється з Runnable на Running . Коли потік припиняється, всі ресурси як для рідного, так і для Java потоку вивільняються.
переоцінка

@overexchange Де можна знайти матеріал про зміну стану.
twlkyao

73

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


35

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

Ще одна різниця між start()і run()в потоці Java полягає в тому, що ви не можете зателефонувати start()двічі. Після запуску другий start()виклик буде кинутий IllegalStateExceptionна Java, тоді як ви можете викликати run()метод кілька разів, оскільки це просто звичайний метод.


21

Насправді Thread.start()створюється новий потік і є власний сценарій виконання.

Thread.start() телефонує run() метод асинхронно, що змінює стан нової теми на Runnable.

Але Thread.run() не створює жодної нової нитки. Натомість він виконує метод запуску в поточному запущеному потоці синхронно.

Якщо ви користуєтеся, Thread.run()то ви взагалі не використовуєте функції багаторічної нитки.


8

виклик run()виконується на виклику потоку, як і будь-який інший метод виклику. тоді як Thread.start()створює нову нитку. виклик run()- це програмна помилка.


7

Якщо ви робите run()в основному методі, нитка основного методу буде викликатиrun метод замість потоку, який потрібно запустити.

start()Метод створює новий потік , і для яких run()метод повинен зробити


"Основний метод" нічого спільного з цим не має.
Маркіз Лорн

3
@EJP, mainписьменник мав на увазі метод виклику. Його відповідь досить хороша. +1 ;-)
dom_beau

1
@dom_beau Якщо це він мав на увазі, він повинен був так сказати. Те, що він сказав, було невірним. У цій відповіді немає нічого «досить хорошого». Це просто заплутана безлад.
Маркіз Лорнський

5

t.start() це метод, який надає бібліотека для вашого коду для виклику, коли потрібно новий потік.

r.run()це метод, який ви надаєте бібліотеці для виклику в новому потоці.


Більшість із цих відповідей пропускають велику картину, яка полягає в тому, що, що стосується мови Java, то між різними іншими методами немає різниці t.start()і r.run()більше.

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

Найбільша відмінність полягає в тому, що більшість коду для t.start()- це нативний код, а в більшості випадків код для r.run()чистого Java. Але це не велика різниця. Код - код. Рідний код важче знайти, і складніше зрозуміти, коли його знайдеш, але все одно просто код підказує комп'ютеру, що робити.

Отже, що робить t.start()?

Він створює новий власний потік, він упорядковує виклик цього потоку t.run(), а потім повідомляє ОС відпустити новий потік. Потім вона повертається.

І що робить r.run() ?

Найсмішніше, що людина, яка задає це запитання, - це людина, яка її написала . r.run()робить все, що ви (тобто розробник, який це написав) створив для цього.


4

Thread.start()Код реєструє Нитку з планувальником, а планувальник викликає run()метод. Крім того, Threadє class, а Runnableінтерфейс.


3

Справа в тому, що учасники виступили в порядку, тому я просто хочу щось додати. Вся справа в тому, що JAVA не підтримує мульти спадкування. Але що робити, якщо ви хочете отримати клас B з іншого класу A, але ви можете походити лише з одного класу. Зараз проблема полягає в тому, як "вивести" з обох класів: A і Thread. Тому ви можете використовувати інтерфейс Runnable.

public class ThreadTest{
   public void method(){
      Thread myThread = new Thread(new B());
      myThread.start;
   }
}

public class B extends A implements Runnable{...

чудово пояснення методу run () за допомогою прикладу про Runnable - інтерфейс і Thread - клас
Pinky Walve

1

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

Якщо ви викликаєте start()метод на Thread, віртуальна машина Java викличе метод run (), і два потоки будуть працювати одночасно - Current Thread ( main()у вашому прикладі) та Other Thread (Runnabler1 у вашому прикладі).

Погляньте на вихідний код start()методу в класі Thread

 /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    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();

У наведеному вище коді ви не можете побачити виклик до run()методу.

private native void start0()відповідає за run()метод виклику . JVM виконує цей нативний метод.


0

У першому випадку ви просто посилаєтесь на run()метод r1іr2 об'єктів.

У другому випадку ви фактично створюєте 2 нові теми!

start() подзвоню run() в якийсь момент!


7
Насправді, start () не буде викликати run (): якщо б це було, то метод run () буде виконаний тим самим потоком, що і запускав start (). Що почне робити (), це створити потік, який викликатиме метод run ().
Бруно Рейс

0

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

метод запуску: - визначено в класі Thread. Коли метод запуску викликається на об'єкт Thread 1- він викликає внутрішньо (nonjava) метод, який називається start0 (); метод.

start0 (); метод: відповідає за низьку обробку (створення стека для потоку та виділення потоку в черзі процесора). У цей момент у нас є потік у стані Ready / Runnable.

2- У той час, коли планувальник потоків вирішує, що потік входить до ядра процесора відповідно до (пріоритет потоку, а також алгоритм планування ОС), метод запуску викликається на об'єкт Runnable (будь то поточний об'єкт потоку Runnable або переданий об'єкт Runnable до конструктора потоків) тут потік переходить у стан запуску і починає виконувати свою задачу (метод запуску)


-2

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

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

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


2
Виклик `run () 'не є способом створення потокових програм. Є лише один спосіб.
Маркіз Лорн

-2

Метод запуску виклику методу Start () методу перезапуску потоку розширеного класу Thread та інтерфейсу реалізованої програми Runnable.

Але зателефонувавши run (), він шукає метод запуску, але якщо клас, що реалізує інтерфейс Runnable, то він викликає run () метод заміни Runnable.

напр .:

`

public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class 
        //implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it 
        //didn't show any error.

a.start();//this call run() of Thread
b.start();//this call run() of Thread
}

class A implements Runnable{
@Override
    public void run() {
            System.out.println("A ");
    }
}

class B extends Thread {

    @Override
    public void run() {
            System.out.println("B ");
    }
}

`

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