В чем разница между Thread start () и Runnable run ()
Скажем, у нас есть эти две 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(); }
И это:
- Зачем использовать ReentrantLock, если вы можете использовать синхронизированный (это)?
- Как я могу атомизировать приращение переменной в Swift?
- Почему назначение целых чисел на естественно выровненной переменной атома на x86?
- Принуждение нескольких streamов к использованию нескольких процессоров, когда они доступны
- .NET Асинхронный stream чтения / записи
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(); }
- Является ли stl-вектор одновременным чтением streamобезопасным?
- Инициализация двух streamов одним и тем же экземпляром исполняемого файла
- В чем разница между параллелизмом, параллелизмом и асинхронными методами?
- Выбор лучшего списка параллелизма в Java
- Неустойчиво дорого?
- Безопасно ли читать указатель на функцию одновременно без блокировки?
- вопрос о примере «Java Concurrency in Practice»
- Как продемонстрировать условия гонки вокруг ценностей, которые не опубликованы должным образом?
Первый пример: Нет нескольких streamов. Оба выполняются в одном (существующем) streamе. Нет создания нитей.
R1 r1 = new R1(); R2 r2 = new R2();
r1
и r2
– это всего лишь два разных объекта classов, которые реализуют интерфейс Runnable
и таким образом реализуют метод run()
. Когда вы вызываете r1.run()
вы выполняете его в текущем streamе.
Второй пример: два отдельных streamа.
Thread t1 = new Thread(r1); Thread t2 = new Thread(r2);
t1
и t2
являются объектами classа Thread
. Когда вы вызываете t1.start()
, он запускает новый stream и вызывает метод run()
внутри r1
чтобы выполнить его в этом новом streamе.
Если вы просто вызываете run()
напрямую, он выполняется в вызывающем streamе, как и любой другой вызов метода. Thread.start()
требуется для создания нового streamа, так что метод runnable run
выполняется параллельно.
Разница в том, что Thread.start()
запускает stream, который вызывает метод run()
, а Runnable.run()
просто вызывает метод run()
для текущего streamа.
Разница в том, что при вызове метода start()
возникает новый stream и run()
код внутри run()
в новом streamе, а если вы вызываете метод run()
напрямую, новый stream не будет создан, а код внутри run()
будет выполнять непосредственно в текущем streamе.
Другое различие между start()
и run()
в streamе Java заключается в том, что вы не можете дважды вызвать start()
. После запуска второй вызов start()
вызовет IllegalStateException
в Java, в то время как вы можете вызвать метод run()
несколько раз, поскольку это обычный метод.
Фактически Thread.start()
создает новый stream и имеет свой собственный сценарий выполнения.
Thread.start()
асинхронно вызывает метод run()
, который изменяет состояние нового streamа на Runnable.
Но Thread.run()
не создает никакого нового streamа. Вместо этого он синхронно выполняет метод запуска в текущей текущей нити.
Если вы используете Thread.run()
вы вообще не используете функции многопоточности.
invoke run()
выполняется в вызывающем streamе, как и любой другой вызов метода. тогда как Thread.start()
создает новый stream. Вызов run()
– программная ошибка.
Thread.start()
регистрирует Thread с планировщиком, и планировщик вызывает метод run()
. Кроме того, Thread
является classом, а Runnable
– интерфейсом.
Если вы выполните run()
в основном методе, stream основного метода вызовет метод run
вместо streamа, который требуется запустить.
Метод start()
создает новый stream и для которого должен run()
метод run()
Точки, которые сделаны членами, все в порядке, поэтому я просто хочу что-то добавить. Дело в том, что JAVA не поддерживает Multi-inheritance. Но что есть, если вы хотите получить class B из другого classа A, но вы можете получить только один class. Теперь проблема заключается в том, как «выводить» из обоих classов: A и Thread. Поэтому вы можете использовать Runnable Interface.
public class ThreadTest{ public void method(){ Thread myThread = new Thread(new B()); myThread.start; } } public class B extends A implements Runnable{...
Большинство из этих ответов пропускают большую картину, которая заключается в том, что в отношении языка Java больше нет различия между t.start()
и r.run()
чем между любыми другими двумя методами.
Они оба – просто методы. Они оба бегут в streamе, который их назвал . Они оба делают то, что они закодировали, и затем они оба возвращаются, все еще в том же streamе, к своим вызывающим.
Самое большое отличие состоит в том, что большая часть кода для t.start()
– это собственный код, в то время как в большинстве случаев код для r.run()
будет чистой Java. Но это не имеет большого значения. Код – это код. Родной код сложнее найти, и сложнее понять, когда вы его найдете, но это все еще только код, который говорит компьютеру, что делать.
Итак, что делает t.start()
?
Он создает новый собственный stream, он упорядочивает этот stream для вызова t.run()
, а затем он сообщает ОС, чтобы запустить новый stream. Затем он возвращается.
И что делает r.run()
?
Самое смешное, что человек, задающий этот вопрос, – это тот, кто его написал . r.run()
делает то, что вы (т. е. разработчик, который его написал) предназначил для этого.
t.start()
– это метод, который библиотека предоставляет для вызова вашего кода, когда вы хотите новый stream.
r.run()
– это метод, который вы предоставляете библиотеке для вызова в новом streamе.
Если вы вызываете метод run()
, вы не используете многопоточную функцию, поскольку метод run()
выполняется как часть streamа вызывающего.
Если вы вызовете метод start()
в Thread, виртуальная машина Java вызовет метод run (), а два streamа будут выполняться одновременно – Current Thread ( main()
в вашем примере) и Other Thread (Runnable r1
в вашем примере).
Посмотрите исходный код метода start()
в classе Thread
/** * Causes this thread to begin execution; the Java Virtual Machine * calls the
run
method of this thread. ** The result is that two threads are running concurrently: the * current thread (which returns from the call to the *
start
method) and the other thread (which executes its *run
method). ** 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();
В вышеприведенном коде вы не можете вызвать метод invocation to run()
.
private native void start0()
отвечает за вызов метода run()
. JVM выполняет этот собственный метод.
Start () метод переадресации вызова метода расширенного classа Thread и интерфейс Runnable реализует.
Но, вызвав run (), он ищет метод run, но если class, реализующий интерфейс Runnable, затем вызывает метод run () override метода 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 "); } }
`
В первом случае вы просто вызываете метод run()
объектов r1
и r2
.
Во втором случае вы фактически создаете 2 новые темы!
start()
в какой-то момент вызовет run()
!
Отдельные методы start () и run () в classе Thread предоставляют два способа создания многопоточных программ. Метод start () запускает выполнение нового streamа и вызывает метод run (). Метод start () немедленно возвращается, и новый stream обычно продолжается до тех пор, пока метод run () не вернется.
Метод run () classа Thread ничего не делает, поэтому подclassы должны переопределять метод с кодом для выполнения во втором streamе. Если stream создается с помощью аргумента Runnable, метод run () streamа выполняет вместо этого метод run () объекта Runnable в новом streamе.
В зависимости от характера вашей streamовой программы вызов метода Thread run () напрямую может давать тот же вывод, что и вызов через метод start (), но в последнем случае код фактически выполняется в новом streamе.