Теперь я понимаю, что когда вызывается 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();
}
...
}
Существуют другие способы реализации синхронизации с использованием классов параллелизма или примитивов mutex / wait / notify Java 1 .Но явная синхронизация между двумя потоками - единственный способ гарантировать требуемое поведение.
Обратите внимание, что вызов doSomething()
в дочернем потоке завершится до освобождения родительского потока, но мы ничего не можем сказатьо порядке исполнения doSomethingElese()
и doSomeMoreStuff()
.(Один может работать раньше другого и наоборот, или они могут работать параллельно.)
1 - Использование wait
/ notify
не рекомендуется, но это может быть вашимединственный вариант, если API параллелизма недоступны;например на Java ME.