Подтвердить что ты не робот

Получает ли главный поток контроль сразу после вызова некоторого метода start() потока?

Например:

public class Example1 {

    public static void main(String[] args) {
        Loop loop = new Loop();
        loop.start(); //printing "Before start"
        System.out.println("After start");
    }
}

Может ли быть проблема с тем, что метод выполнения loop заканчивается до выполнения последней строки, которая печатает "После запуска"?

4b9b3361

Ответ 1

Как только вы начнете многопоточность, вам было бы разумно отказаться от всех предположений о порядке, в котором будут выполняться потоки.

Если это важно, вы можете использовать операции синхронизации, но без них все ставки отключены.

Ответ 2

Да, у вас нет контроля над тем, как потоки выполняются/планируются JVM.

Если вы хотите ввести какой-то порядок (выполнить последовательно два потока), самым простым способом сделать это было бы использование одного из объектов Lock, которые предоставляет Java.

Ответ 3

В основном вы спрашиваете о безопасности потоков в Java (по крайней мере, это то, что я понимаю из вопроса). Как уже упоминалось ранее, рекомендуется отказаться от любых допущений, которые могут возникнуть в отношении порядка выполнения при запуске нескольких потоков.

Однако (!), можно использовать принципы проектирования и критическое мышление для моделирования вашего приложения таким образом, чтобы в результате многопоточности не возникало нежелательных побочных эффектов.

Для начала вы можете прочитать эту статью на Проектирование инициализации объектов Суть статьи в том, что вы должны думать о своих классах как finite state machines. Если вы не знаете, что это такое: finite state machines работают в наборе состояний (отсюда и название).

Идея заключается в том, что когда вы находитесь в состоянии (A), вы можете определить поведение, которое может выполнять это конкретное состояние: (A) -> (B), (A) -> (C) Я могу перейти из состояния (A) в состояние (B) и (C), но не указывать (D) (если он существует). Это мышление важно для понимания того, что ваше приложение МОЖЕТ в любой ситуации. (Изобразительные государственные машины Wikipedia)

Как только вы это понимаете, вы можете перейти на Исправление:

Существует три способа безопасного создания объектов:

  • Синхронизация критических разделов
  • Сделать его неизменным
  • Используйте потокобезопасную оболочку

Каждый подход имеет свои собственные преимущества/недостатки, которые описаны в документации Java:

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

Ответ 4

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

public class Example1 {

    public static void main(String[] args) {
        Loop loop = new Loop();
        System.out.println("Before start");
        loop.start(); //printing "Before start"
        System.out.println("After start");
        loop.join();
        System.out.println("After join");
    }
}

"Перед началом" всегда будет напечатано до того, как будет выполнен loop.run().

"После объединения" всегда будет напечатано после завершения loop.run().

"После запуска" не гарантируется, когда он будет напечатан относительно loop.run(); он может быть до, он может быть после, он может быть во время выполнения чередуется с операторами печати в loop.run().

Если вам нужны гарантии, вам понадобятся другие утилит синхронизации, такие как блокировки и семафоры.