Cara memeriksa apakah utas saat ini bukan utas utama

392

Saya perlu memeriksa apakah utas yang menjalankan bagian kode tertentu adalah utas utama (UI) atau tidak. Bagaimana saya bisa mencapai ini?

Charlie-Blake
sumber
contoh untuk menunjukkan dengan contoh thread code2concept.blogspot.in/2015/02/...
nitesh

Jawaban:

709
Looper.myLooper() == Looper.getMainLooper()

jika ini mengembalikan true, maka Anda berada di utas UI!

Jasmani
sumber
Bagaimana Anda menjalankan kode ini di junit?
John Sardinha
123

Anda dapat menggunakan kode di bawah ini untuk mengetahui apakah utas saat ini adalah UI / Utas utama atau tidak

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

atau Anda juga bisa menggunakan ini

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

Ini pertanyaan serupa

AAnkit
sumber
8
Haruskah seseorang menganggap yang terakhir sebagai opsi yang lebih aman karena tidak ada jaminan bahwa utas sewenang-wenang apapun terkait dengan Looper (dengan asumsi bahwa utas utama selalu dikaitkan dengan looper)?
Janus Varmarken
Looper.myLooper()akan mengembalikan nol jika utas tidak dikaitkan dengan Looper. Jadi keduanya aman dan memiliki hasil yang sama tetapi yang pertama sedikit lebih lambat saat mencari di dalam peta untuk mengetahui looper dan utas terkait dan melakukan beberapa hal lainnya.
Saeed Masoumi
59

Cara terbaik adalah cara yang paling jelas, paling kuat: *

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

Atau, jika platform runtime adalah API level 23 (Marshmallow 6.0) atau lebih tinggi:

Looper.getMainLooper().isCurrentThread()

Lihat Looper API . Perhatikan bahwa panggilan Looper.getMainLooper()melibatkan sinkronisasi (lihat sumbernya ). Anda mungkin ingin menghindari overhead dengan menyimpan nilai kembali dan menggunakannya kembali.

   * kredit greg7gkb dan 2cupsOfTech

Michael Allan
sumber
Apa yang Anda maksud dengan "di bawah API 23 atau lebih tinggi"? Itu tidak masuk akal bagi saya..Juga jawaban yang sama persis diposting oleh AAnkit, di bawah ini ..
Mike
@ Mike Terima kasih, saya memperbaiki bit API. AAnkit sebenarnya nikmat Looper.myLooper() == Looper.getMainLooper(), yang menurut saya kurang jelas. Saya kredit greg7gkb.
Michael Allan
1
haruskah ini perbandingan dengan == atau sama dengan () karena Android Studio meningkatkan peringatan?
2cupsOfTech
@ 2cupsOfTech Pada pemikiran kedua, itu saran yang bagus. Saat ini kedua tes adalah sama pada saat runtime karena Thread tidak menimpa equals, dan jatuh kembali ke ==, tetapi itu bisa berubah di masa depan. Jadi saya mengoreksi jawabannya.
Michael Allan
25

Merangkum solusi, saya pikir itu yang terbaik:

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

Dan, jika Anda ingin menjalankan sesuatu pada utas UI, Anda dapat menggunakan ini:

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

Anda bisa mengeceknya

if(Looper.myLooper() == Looper.getMainLooper()) {
   // You are on mainThread 
}else{
// you are on non-ui thread
}
Lovekush Vishwakarma
sumber
2

Izinkan saya untuk mengawali ini dengan: Saya mengakui posting ini memiliki tag 'Android', namun, pencarian saya tidak ada hubungannya dengan 'Android' dan ini adalah hasil teratas saya. Untuk itu, untuk pengguna SO Java non-Android yang mendarat di sini, jangan lupakan:

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

Setelah mengatur ini, di tempat lain dalam kode Anda, Anda dapat dengan mudah memeriksa apakah Anda akan mengeksekusi di utas utama dengan:

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

Agak malu saya telah mencari sebelum mengingat ini, tapi mudah-mudahan itu akan membantu orang lain!

ThatOneGuy
sumber
1

Anda dapat memverifikasinya di android ddms logcat di mana id proses akan sama tetapi id utas akan berbeda.

Vishwanath.M
sumber
1

Xamarin.Androidport: ( C#)

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

Pemakaian:

if (IsMainThread) {
    // you are on UI/Main thread
}
Mehdi Dehghani
sumber
-6

Anda dapat mencoba Thread.currentThread (). IsDaemon ()

Shailendra Singh
sumber
Saya tidak yakin utas UI adalah daemon tetapi saya akan mempercayai Anda tentang ini. Tetapi bagaimana Anda akan membuat perbedaan dengan Daemon Thread yang saya dapat (tetapi tidak seharusnya) buat.
AxelH
Saya menguji di aplikasi web saya, itu menunjukkan bahwa utas UI adalah utas Daemon. Saya menaruh beberapa break point debug di lingkungan gerhana dan memverifikasinya. Detail utas ditampilkan sebagai Utas [http-bio-8080-exec-7,5, utama]. Mengklik pada beberapa halaman UI dan memeriksa titik debug.
Shailendra Singh
Juga, bahkan jika dalam nama thread rinciannya menampilkan 'main' tetapi memanggil setDaemon (true) pada objek thread akan membuatnya daemon.
Shailendra Singh
Anda tidak membaca bagian yang baik ... Saya tidak ragu-ragu (sepenuhnya) tentang itu menjadi Daemon, saya mengatakan bahwa Anda tidak dapat membuat perbedaan dengan utas Daemon lain seperti ini.
AxelH
Dengan kata lain: utas utama mungkin merupakan utas daemon, tetapi tidak semua utas daemon adalah utas utama. (Mengidentifikasi utas utama adalah apa yang ditanyakan di sini.)