Заставить поток переключиться на контекст

У меня есть функция foo, в которой я хочу создать и запустить поток, но отложить его выполнение до завершения, пока foo не вернется.

Я добился этого, введя задержку в новый поток, используя вызов sleep, эффективно (я думаю) вызывая переключение контекста.

String foo()
{
    // do some stuff

    Runnable task1 = () -> 
    {
        Thread.sleep(100);

        // do some stuff
    };

    // start the thread
    new Thread(task1).start();

    return "bar";
}

Кажется, это работает - то есть foo всегда возвращается до того, как task1 сделает свое дело.

Правильно ли использовать sleep? Или есть способ лучше?

Я думаю, что лучший способ сделать это - использовать priority.

swayamraina 12.04.2018 09:56

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

Ben 12.04.2018 09:58

@Ben Пожалуйста, расскажите подробнее.

ksl 12.04.2018 09:59

Что я должен уточнить? Когда вы запускаете потоки, вы передаете порядок выполнения планировщику, который решает, когда какой поток должен что-то делать. Добавление sleeps туда, чтобы «дать время другим потокам наверстать упущенное» - это решение, которое может работать в некоторых случаях или, может быть, даже большую часть времени, но не дает никаких гарантий.

Ben 12.04.2018 10:01

Нет гарантии, что он будет работать всегда. Возможно, вы захотите запустить поток после вызова метода foo (). Вы можете создать поток внутри метода и заставить его возвращать ссылку на него. например: foo (). start ();

nitnamby 12.04.2018 10:05

@Ben Новый поток не требует предварительной инициализации. Просто нужно не завершить, прежде чем foo вернется.

ksl 12.04.2018 10:05

Если он не должен завершаться до того, как foo вернется, тогда начните, если после того, как foo вернется. В качестве альтернативы используйте wait до завершения и вызовите на нем notify, чтобы остановить ожидание.

Ben 12.04.2018 10:11
Thread.sleep(n) гарантирует только то, что вызывающий поток будет заблокирован на п миллисекунд. нет может гарантировать, что какой-либо другой поток не будет заблокирован более чем на п миллисекунды (например, из-за большой потребности в процессоре со стороны других, не связанных процессов).
Solomon Slow 16.04.2018 18:56
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
202
1

Ответы 1

Вы можете использовать Semaphore для правильного управления всем этим.

String foo() {
    Semaphore waitUntilWeReturn = new Semaphore(-1);
    Runnable task1 = new Runnable() {
        @Override
        public void run() {
            awaitPermissionToProceed();
            // do some stuff

        }

        private void awaitPermissionToProceed() {
            try {
                waitUntilWeReturn.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    // start the thread
    new Thread(task1).start();

    waitUntilWeReturn.release();
    return "bar";
}

Можно ли сразу переключить контекст на новый поток при вызове release и выполнить его до завершения до возврата foo?

ksl 12.04.2018 10:42

@ksl - Да, при почти невероятных обстоятельствах - но гораздо более маловероятно, чем простой Thread.sleep. Это может произойти в коротком окне очень (всего несколько инструкций).

OldCurmudgeon 12.04.2018 10:47

@OldCurmudgeon, Re, "короткое окно очень". По моему опыту, когда вы предприняли шаги, чтобы убедиться, что произойдет какая-то нежелательная вещь почти никогда, то на самом деле вы убедились, что если и когда это в конечном итоге произойдет, делает произойдет в производстве какого-то важного клиента. системе вместо того, чтобы происходить в вашей собственной тестовой оснастке.

Solomon Slow 16.04.2018 19:00

@ksl, ответ OldCurmudgeon не освобождает семафор до тех пор, пока функция foo() не сделает все, что она собирается делать. Почему имеет значение, действительно ли вызов foo() вернулся или нет? (т.е. что плохого может случиться, если ...do some stuff... начнет выполняться до того, как foo() вернется?)

Solomon Slow 16.04.2018 19:19

@jameslarge Это упрощенный пример. делает имеет значение, чем сначала возвращается foo().

ksl 16.04.2018 21:43

@ksl, Да, в исходном вопросе вы сказали, что не хотите, чтобы do some stuff запускался до тех пор, пока не вернется foo(). Я спрашиваю почему. Причина, по которой я спрашиваю, заключается в том, что я не вижу для этого никакой причины, когда смотрю на ваш пример. Думаю, у вас над упростил. Если важно не запускать do some stuff до тех пор, пока foo() не вернется, то причиной должно быть что-то, что происходит на месте вызова. Вы не показали нам место звонка. Вы, вероятно, не получите удовлетворительного ответа, если не сможете показать код, который имеет значение (или какой-нибудь продезинфицированный прокси для него).

Solomon Slow 16.04.2018 22:26

Другие вопросы по теме