Как проверить, не является ли текущий поток основным потоком


Ответы:



123

Вы можете использовать приведенный ниже код, чтобы узнать, является ли текущий поток пользовательским интерфейсом / основным потоком или нет

if(Looper.myLooper() == Looper.getMainLooper()) {
   // Current Thread is Main Thread.
}

или вы также можете использовать это

if(Looper.getMainLooper().getThread() == Thread.currentThread()) {
   // Current Thread is Main Thread.
}

Вот похожий вопрос


8
Следует ли рассматривать последний как более безопасный вариант, поскольку нет гарантии, что какой-либо произвольный поток связан с Looper (при условии, что основной поток всегда связан с Looper)?
Янус Вармаркен

Looper.myLooper()вернет ноль, если поток не связан с Looper. Таким образом, оба безопасны и имеют одинаковый результат, но первый немного медленнее, когда он ищет внутри карты, чтобы найти петлитель и связанный с ним поток и сделать что-то еще.
Саид Масуми

59

Лучший способ - самый ясный, самый надежный способ: *

Thread.currentThread().equals( Looper.getMainLooper().getThread() )

Или, если рабочая среда имеет уровень API 23 (Marshmallow 6.0) или выше:

Looper.getMainLooper().isCurrentThread()

Смотрите API Looper . Обратите внимание, что вызов Looper.getMainLooper()включает синхронизацию (см. Источник ). Возможно, вы захотите избежать накладных расходов, сохраняя возвращаемое значение и используя его повторно.

   * кредит greg7gkb и 2cupsOfTech


Что вы подразумеваете под «по API 23 или выше»? Это не имеет большого смысла для меня .. Точно такой же ответ был опубликован AAnkit, ниже ..
Майк

@ Майк Спасибо, я исправил API-бит. AAnkit на самом деле одобряет Looper.myLooper() == Looper.getMainLooper(), что, я думаю, менее понятно. Я кредит greg7gkb.
Майкл Аллан

1
должно ли это быть сравнение с == или equals (), поскольку Android Studio вызывает предупреждение?
2cupsOfTech

@ 2cupsOfTech На 2-й мысли, это хороший совет. В настоящее время оба теста одинаковы во время выполнения, потому что Thread не переопределяет equalsи поэтому возвращается к нему ==, но это может измениться в будущем. Поэтому я исправил ответ.
Майкл Аллан

25

Подводя итог решениям, я думаю, что это лучшее:

boolean isUiThread = VERSION.SDK_INT >= VERSION_CODES.M 
    ? Looper.getMainLooper().isCurrentThread()
    : Thread.currentThread() == Looper.getMainLooper().getThread();

И, если вы хотите запустить что-то в потоке пользовательского интерфейса, вы можете использовать это:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
       //this runs on the UI thread
    }
});


2

Позвольте мне предвосхитить это следующим образом: я признал, что в этом сообщении есть тег «Android», однако мой поиск не имеет ничего общего с «Android», и это был мой лучший результат. В связи с этим, для не-Android SO пользователей Java, приземляющихся здесь, не забудьте о:

public static void main(String[] args{
    Thread.currentThread().setName("SomeNameIChoose");
    /*...the rest of main...*/
}

После установки этого в другом месте вашего кода вы можете легко проверить, собираетесь ли вы выполнять в главном потоке:

if(Thread.currentThread().getName().equals("SomeNameIChoose"))
{
    //do something on main thread
}

Немного смутившись, я искал, прежде чем вспомнить это, но, надеюсь, это поможет кому-то еще!


1

Вы можете проверить это в android ddms logcat, где идентификатор процесса будет таким же, но идентификатор потока будет другим.


1

Xamarin.Androidпорт: ( C#)

public bool IsMainThread => Build.VERSION.SdkInt >= BuildVersionCodes.M
    ? Looper.MainLooper.IsCurrentThread
    : Looper.MyLooper() == Looper.MainLooper;

Применение:

if (IsMainThread) {
    // you are on UI/Main thread
}

-6

Вы можете попробовать Thread.currentThread (). IsDaemon ()


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

Я протестировал в своем веб-приложении, оно показывает, что поток пользовательского интерфейса является потоком Daemon. Я поместил некоторые точки прерывания отладки в среду затмения и проверил это. Деталь темы показана как Тема [http-bio-8080-exec-7,5, main]. Кликнул по некоторым страницам пользовательского интерфейса и проверил точку отладки.
Шайлендра Сингх

Кроме того, даже если в имени потока указано, что он показывает 'main', но вызов setDaemon (true) для объекта потока сделает его демоном.
Шайлендра Сингх

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

Другими словами: основной поток может быть потоком демона, но не все потоки демона являются основным потоком. (Идентификация главной
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.