Thread.join предназначен для "заморозки" вашей темы!
Когда вы вызываете объединение, текущий поток приостанавливается до тех пор, пока не завершится поток, к которому он присоединяется. В вашем случае это зависание происходит потому, что экземпляр MyThread
не завершается своевременно.
Одна вещь, которая может вас здесь кусать - вам нужно объявить переменную прерывания как volatile
, чтобы изменения были надежно видны другим потокам . Поскольку вы этого не делаете, ваш MyThread может полностью увидеть кэшированную версию переменной abort, где она всегда истинна. Вот краткое описание этого здесь .
Редактировать: Я пропустил ваше заявление о том, что оно работает локально, но не на удаленной машине. На самом деле это не так уж редко с гоночными условиями, связанными с параллелизмом, поскольку они могут проявляться или не проявляться в зависимости от различных факторов, таких как настройка оборудования, нагрузка на компьютер и т. Д. В этом случае, например, если на вашем локальном компьютере есть только один физический процессор / ядро, тогда ваш ошибочный код будет вероятно работать нормально; там только один кэш ЦП, поэтому другой поток, скорее всего, «увидит» основной поток, изменяющий флаг abort
, хотя он явно не помечен как энергозависимый. Теперь перенесите это на многоядерный компьютер, и если потоки будут распределены по отдельным ядрам, они будут использовать отдельные кэши и вдруг не увидят изменений в энергонезависимых кэшированных переменных.
Вот почему очень важно понимать последствия параллелизма и именно то, что гарантировано, потому что сбои не проявляются согласованным образом.
Обновление реакция: если это все еще не работает, когда прерывание изменчиво, это звучит так же, как MyThread
не проверяет переменную достаточно часто. Имейте в виду, что он только «заметит», что флаг прерывания был установлен непосредственно после вытягивания другого вида строки из вашего вида курсора. Если возможно, что обработка одного элемента относительно гистограммы может занять много времени, тогда, конечно, он не увидит флаг в течение этого времени.
Возможно, вам просто нужно чаще проверять флаг отмены. Вы говорите, что звоните invokeAndWait
каждые 500 мс; Вы должны проверять свой флаг прерывания перед каждым вызовом, поэтому вам нужно подождать не более 500 мсек, чтобы поток завершился! Просмотрите эту часть своего кода и посмотрите, есть ли какие-либо внутренние циклы, которые вы можете изменить, чтобы они выглядели как while (... && !abort)
.
Другим перпендикулярным подходом является также начало прерывания потока. В частности, SwingUtilities.invokeAndWait является прерываемым, поэтому если вы вызываете thread.interrupt()
в своем методе stopThread()
, то вызов invokeAndWait завершится очень быстро (с помощью исключения InterruptedException), вместо того, чтобы ждать, пока он завершится нормально, прежде чем ваш код получит возможность проверить флаг отмены снова. Это дает дополнительное преимущество: если для выполнения какой-либо другой прерываемой операции требуется очень много времени, она также сразу же возвращается. (В этом случае вы, вероятно, захотите явно перехватить InterruptedException в своем бите обработки кода; вам не нужно ничего делать для его обработки как такового, просто примите это как знак, чтобы проснуться и снова проверить флаг Прочитайте эту превосходную статью Developerworks для получения дополнительной информации об обработке InterruptedExceptions).
Наконец, если у вас все еще есть проблемы, то вам поможет отладка старой доброй печати. Если у вас будет MyThread
печать на консоль (или, возможно, какой-нибудь файл журнала) каждый раз, когда он проверяет флаг отмены, вы сможете увидеть, не связана ли проблема с зависанием самого MyThread; так как в этом случае он никогда не завершится и вызывающий поток никогда не вернется из вызова join (). Перемещение проверки флага прерывания вниз вниз, вероятно, поможет в этом.