Почему мы вызываем метод потока start()
, который по очереди вызывает метод run()
, почему бы нам не вызвать метод run()
?
Почему мы вызываем метод Thread.start(), который по очереди вызывает метод run?
Ответ 1
[...] почему бы нам не вызвать метод run()?
Метод run()
- это обычный метод (переопределенный вами). Как и в случае с любым другим обычным методом и вызовом его напрямую, текущий поток будет выполняться run()
.
Вся магия происходит внутри start()
. Метод start()
приведет к тому, что JVM создаст новый поток и выполнит выполняемый новый поток run()
.
Ответ 2
Если вы вызываете метод run(), его тело выполняется в контексте текущего потока. Когда вы вызываете метод start()
, создается новый поток и в этом новом потоке выполняется run()
метод.
Ответ 3
Даже если программно мы не создаем нить, для каждого приложения O.S создаст поток по умолчанию для выполнения своего кода с CPU.
Прямой вызов метода запуска приведет к тому, что этот метод выполнения будет выполняться в этом основном потоке, заданном O.S.
Но намерение создания класса потока состоит в том, чтобы убедиться, что метод run выполняется в другом потоке. Если диспетчер потоков O.S не создает поток, ваш метод запуска не будет выполняться в отдельном потоке. Чтобы запросить O.S создать отдельный поток, вы должны вызвать метод start(), который отправит запрос O.S для создания потока. После того, как O.S создаст поток, O.S автоматически вызовет метод run вашего класса потока в этом недавно созданном контексте потока. И, следовательно, ваша цель создания отдельного потока и выполнения вашего метода выполнения в отдельном потоке будет выполнена.
Если вы вызываете метод run напрямую, то аналогичный O.S не создает нити для вас, и основной поток по умолчанию выполнит ваш метод запуска. Нет смысла создавать для этого отдельный класс потока!
Надеюсь, я поняла. Дайте мне знать, если вам нужно больше объяснений, чтобы ответить на ваш вопрос.
Примечание. Несмотря на то, что книги говорят, что JVM создает потоки, внутри JVM придется отправить запрос на драйвер диспетчера потоков уровня O.S, чтобы создать новый поток в пуле потоков. Вот почему я использую термин O.S здесь больше, чем JVM.
Ответ 4
Runnable
- это просто интерфейс. Класс, реализующий Runnable
, ничего особенного, он просто имеет метод run
.
Thread#start
- это изначально реализованный метод, который создает отдельный поток и вызывает метод Thread
run
, выполняющий код в новом потоке.
Thread
реализует Runnable
. Код для run
выглядит следующим образом:
@Override
public void run() {
if (target != null) {
target.run();
}
}
Если экземпляр Thread
был создан путем передачи Runnable
в конструктор Thread
, вызывается метод Runnable
run
.
В противном случае классы, расширяющие Thread
, должны переопределить метод run
, чтобы start
работал.
Вызов run
на Thread
НЕ создает новый поток.
Ответ 5
Почему мы вызываем метод start() объекта потока, который по очереди вызывает метод run()
Нет, нет. start()
вызывает операционную систему, которая запускает новый поток, который (для упрощения) вызывает метод run()
. Тем временем метод start()
уже вернулся к вызывающему. Они не эквивалентны.
Ответ 6
Если поток был создан, но не запущен, он, как говорят, находится в новом состоянии.
До тех пор, пока не будет вызван метод start() в экземпляре потока, он не будет считаться живым.
Если вы не вызываете метод start() во вновь созданный поток экземпляра потока, не считаетесь чтобы быть живым.
Если метод start() не вызывается, а метод run() напрямую вызывается в экземпляре Thread, код внутри метода run() не будет запускаться в отдельном новом потоке, но он начнет работать в существующем потоке.
СМОТРЕТЬ ПРОБЛЕМУ В ПРИМЕРЕ
class Multi extends Thread{
public void run(){
for(int i=1;i<5;i++){
try{Thread.sleep(500);}catch(InterruptedException e){System.out.println(e);}
System.out.println(i);
}
}
public static void main(String args[]){
Multi t1=new Multi();
Multi t2=new Multi();
t1.run();
t2.run();
}
}
Output:1
2
3
4
5
1
2
3
4
5
Как вы можете видеть в вышеприведенной программе, что нет контекстного переключения, потому что здесь t1 и t2 будут рассматриваться как обычный объект, а не объект потока.
Ответ 7
Вы не должны напрямую ссылаться на метод run(). Если вы вызовете метод run() напрямую, он просто будет выполняться в потоке вызывающего, а не в качестве собственного потока. Вместо этого вам нужно вызвать метод start(), который планирует поток с помощью JVM. JVM вызовет соответствующий метод run(), когда ресурсы и процессор будут готовы. JVM не гарантирует правильность вызова метода run(), когда вызывается метод start(), или в том порядке, в котором вызывается метод start(). Специально для компьютеров есть один процессор, невозможно одновременно запускать все запущенные потоки. JVM должен реализовать схему планирования, которая разделяет процессор среди всех запущенных потоков. Поэтому, когда вы вызываете методы start() из более чем одного потока, последовательность выполнения соответствующих методов run() является случайной, управляемой только JVM.
Ответ 8
Я предполагаю, что вы говорите о начале потока. Если в этом случае причина, по которой вы не вызываете метод run напрямую, заключается в том, что вы будете вызывать метод, а не запускать поток.
Ответ 9
Когда мы используем метод start, создается новый поток, а затем код внутри метода запуска будет выполняться для каждого нового потока.
Использование метода start создает два стека для каждого потока, стек и собственный стек.
Но метод Run
вызывает только execute
код внутри метода Run
последовательно, так как вызов метода запуска не создает разные стеки.
Пример
import java.util.concurrent.TimeUnit;
public class thread implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
Thread gg=new Thread(new thread());
Thread gg1=new Thread(new thread());
gg.run();
gg1.start();
/*gg.start();
gg1.start();*/
}
@Override
public void run() {
for(int i=0;i<5;i++)
{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Hello..." + i);
}
}
}
Ответ 10
Если мы хотим, мы можем вызвать метод run()
, но если мы вызовите метод run, он будет запущен как обычный метод Java. В то время как мы называем start(
), JVM
создает новый поток, и в этом потоке будет выполняться метод run.
Ответ 11
start() и методы run() используются для запуска потока. Метод run() - это обычный метод, он переопределяет пользователя, который будет вызывать текущий поток. Метод start() косвенно запускает метод run() и создает новый поток.
Ответ 12
Это связано с дизайном многопоточности в Java.
Вызов start ()
запустит новый поток, а вызов метода run()
не запустит новый поток.
Если вы вызываете метод start()
в Thread, виртуальная машина Java вызовет метод run(), и одновременно будут выполняться два потока - Current Thread и Other Thread или Runnable.
Посмотрите исходный код метода start()
в класс темы
/**
* 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 создает собственный поток, соответствующий java-потоку, и вызывает метод run()
.
Обратитесь к этому вопросу для исходного кода собственных методов:
Ответ 13
Различие заключается в том, что если мы выполним метод run методом start(), он создаст новый поток, где мы можем выполнить метод run, иначе метод run() будет выполняться в потоке, создаваемом JVM в public static void main(). Это всего лишь точка многопоточности, для запуска различных действий для новых потоков.