То, почему выполняется () не сразу названный, когда запускаются () обратилось к объекту потока в Java

Или это?
У меня есть объект потока от:

Thread myThread = new Thread(pObject);

То, где pObject является объектом класса, реализовывая интерфейс Runnable, и затем у меня есть метод запуска, обратилось к объекту потока как так:

myThread.start();

Теперь, мое понимание - то, что то, когда запускаются () называют, JVM неявно (и сразу) называет выполнение () методом, который может быть переопределен (как это находится в моем случае),

Однако в моем случае, кажется, что запуск () метод сразу не называют (как желаемый), но пока другие операторы/методы не завершаются от блока вызова т.е. если у меня был метод после запуска () вызов как так:

myThread.start();
doSomethingElse();

doSomthingElse () выполняется перед выполнением () метод выполняется вообще.
Возможно, я неправ с начальной предпосылкой, которые работают (), всегда называется прямо после того, как запуск () называют. Помогите! Желаемое снова делает выполнение выполненным () прямо после того, как запустятся ().Спасибо.

7
задан UmNyobe 1 May 2014 в 10:22
поделиться

5 ответов

Насколько я понимаю, когда вызывается start (), JVM неявно (и немедленно) вызывает run ( ) метод ...

Это неверно. Он неявно вызывает run () , но вызов не обязательно происходит немедленно.

Реальность такова, что новый поток становится доступным для планирования в определенный момент времени после выполнения вызова start () . Фактическое планирование зависит от встроенного планировщика. Это может произойти немедленно, или родительский поток может продолжаться в течение некоторого периода до того, как будет запланирован дочерний поток.

Чтобы ваш поток запускался немедленно (или, если быть более точным, запускать его до doSomethingElse () ), вам необходимо выполнить явную синхронизацию; например что-то вроде этого:

    java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
    new Thread(new MyRunnable(latch)).start();
    latch.await(); // waits until released by the child thread.
    doSomethingElse();

где

class MyRunnable implements Runnable {
    private CountDownLatch latch;
    MyRunnable (CountDownLatch latch) { this.latch = latch; }
    public void run() {
        doSomeStuff();
        latch.countDown(); // releases the parent thread
        doSomeMoreStuff();
    }
    ...
}

Есть другие способы реализовать синхронизацию с использованием классов параллелизма или Java-примитивов mutex / wait / notify 1 . Но явная синхронизация между двумя потоками - единственный способ гарантировать требуемое поведение.

Обратите внимание, что вызов doSomething () в дочернем потоке завершится до того, как родительский поток будет освобожден, но мы ничего не можем сказать о порядке выполнения doSomethingElese () и doSomeMoreStuff () . (Один может выполняться раньше другого и наоборот, или они могут работать параллельно.)


1 - Использование wait / notify не рекомендуется, но может быть единственным вариант, если API параллелизма недоступны; например на Java ME.

11
ответ дан 6 December 2019 в 04:51
поделиться

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

16
ответ дан 6 December 2019 в 04:51
поделиться

Когда вы вызываете myThread.start () , ваш поток становится доступным для выполнения. Будет ли он действительно получать процессор и как долго - это решать планировщику ОС. Фактически, ваш run () может немедленно получить управление, но потерять его, прежде чем он сможет сделать что-нибудь, что вы заметите. Единственный способ убедиться, что ваш поток выполняет то, что вам нужно до doSomethingElse () , - это использовать явную синхронизацию.

6
ответ дан 6 December 2019 в 04:51
поделиться

Вы начали новую беседу. Этот поток работает параллельно с потоком, который его запустил, поэтому порядок может быть следующим:

pObject.run();
doSomethingElse();

или

doSomethingElse();
pObject.run();

или, что более вероятно, произойдет какое-то пересечение. pObject.run () может выполняться в середине doSomethingElse () или наоборот, или один запускается до завершения другого и так далее. Важно понимать это и понимать, что имеется в виду под атомарной операцией, иначе вы обнаружите, что действительно трудно найти ошибки.

Еще сложнее, если два или более потока обращаются к одним и тем же переменным. Значение в одном потоке может никогда никогда не обновляться в одном потоке при определенных обстоятельствах.

Я настоятельно рекомендую:

  1. Вы не делайте свою программу многопоточной, если вам не абсолютно это необходимо; и

  2. Если да, купите и прочитайте от корки до корки книгу Брайана Гетца Java Concurrency in Practice .

3
ответ дан 6 December 2019 в 04:51
поделиться

run () - это первое, что в вашем коде выполняет новый поток, но есть некоторые настройки, которые новый поток выполняет в первую очередь. , и нет никакой гарантии, что какой-либо значительный объем работы будет выполнен новым потоком до того, как исходный поток перейдет к вызову doSomethingElse () .

Вы правы, что здесь нет никаких гарантий. Предположения о поведении многопоточного кода - источник большой боли - постарайтесь не делать этого!

13
ответ дан 6 December 2019 в 04:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: