วิธีการตรวจสอบว่าเธรดปัจจุบันไม่ใช่เธรดหลักหรือไม่


391

ฉันต้องตรวจสอบว่าเธรดที่รันโค้ดบางส่วนเป็นเธรดหลัก (UI) หรือไม่ ฉันจะบรรลุสิ่งนี้ได้อย่างไร


ตัวอย่างเพื่อสาธิตด้วยเธรดตัวอย่างcode2concept.blogspot.in/2015/02/…
nitesh

คำตอบ:



122

คุณสามารถใช้โค้ดด้านล่างเพื่อทราบว่าเธรดปัจจุบันเป็น UI / เธรดหลักหรือไม่

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

หรือคุณสามารถใช้สิ่งนี้

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

นี่คือคำถามที่คล้ายกัน


8
ควรพิจารณาตัวเลือกหลังเป็นตัวเลือกที่ปลอดภัยกว่าเพราะไม่มีการรับประกันว่าเธรดใด ๆ ที่เกี่ยวข้องกับ Looper (สมมติว่าเธรดหลักนั้นสัมพันธ์กับ looper เสมอ)?
Janus Varmarken

Looper.myLooper()จะคืนค่า null ถ้าเธรดไม่เกี่ยวข้องกับ Looper ดังนั้นทั้งคู่จึงปลอดภัยและได้ผลเหมือนกัน แต่อันแรกช้ากว่าเล็กน้อยในขณะที่ค้นหาภายในแผนที่เพื่อค้นหา looper และเธรดที่เกี่ยวข้องและทำสิ่งอื่น ๆ
Saeed Masoumi

59

วิธีที่ดีที่สุดคือวิธีที่ชัดเจนและแข็งแกร่งที่สุด: *

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

หรือหากแพลตฟอร์มรันไทม์คือ API ระดับ 23 (Marshmallow 6.0) หรือสูงกว่า:

Looper.getMainLooper().isCurrentThread()

ดูLooper API โปรดทราบว่าการโทรLooper.getMainLooper()เกี่ยวข้องกับการซิงโครไนซ์ (ดูแหล่งที่มา ) คุณอาจต้องการหลีกเลี่ยงค่าใช้จ่ายโดยการเก็บค่าส่งคืนและนำกลับมาใช้ใหม่

   * เครดิตgreg7gkbและ2cupsOfTech


คุณหมายถึงอะไร "ภายใต้ API 23 หรือสูงกว่า" ที่ไม่เหมาะสมกับฉัน .. นอกจากนี้ยังมีคำตอบเดียวกันที่ถูกโพสต์โดย AAnkit ด้านล่าง ..
Mike

@ ไมค์ขอบคุณฉันคงบิตของ API AAnkit ชอบจริงLooper.myLooper() == Looper.getMainLooper()ซึ่งฉันคิดว่าชัดเจนน้อยกว่า ฉันให้เครดิต greg7gkb
Michael Allan

1
นี่ควรเป็นการเปรียบเทียบกับ == หรือเท่ากับ () เนื่องจาก Android Studio กำลังแจ้งเตือนหรือไม่
2cupsOfTech

@ 2cupsOfTech บนความคิดที่ 2 นั่นเป็นคำแนะนำที่ดี ขณะนี้การทดสอบทั้งสองอย่างเหมือนกันที่รันไทม์เนื่องจากเธรดไม่ได้แทนที่equalsดังนั้นจึงกลับไปที่==แต่อาจเปลี่ยนแปลงได้ในอนาคต ดังนั้นฉันจึงแก้ไขคำตอบ
Michael Allan

25

สรุปการแก้ปัญหาฉันคิดว่านั่นเป็นวิธีที่ดีที่สุด:

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

และหากคุณต้องการเรียกใช้งานบางอย่างบนเธรด UI คุณสามารถใช้สิ่งนี้:

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 โดยที่ id กระบวนการจะเหมือนกัน แต่ id ของเธรดจะแตกต่างกัน



-6

คุณสามารถลองใช้ Thread.currentThread (). isDaemon ()


ฉันไม่แน่ใจว่าเธรด UI นั้นเป็นภูต แต่ฉันจะเชื่อคุณในสิ่งนี้ แต่คุณจะสร้างความแตกต่างด้วย Daemon Thread ที่ฉันสามารถสร้าง (แต่ไม่ควร) ได้อย่างไร
AxelH

ฉันทดสอบในเว็บแอปของฉันมันแสดงให้เห็นว่า UI thread เป็น Daemon thread ฉันใส่จุดพักตรวจแก้จุดบกพร่องในสภาพแวดล้อมคราสและตรวจสอบแล้ว รายละเอียดเธรดแสดงเป็นเธรด [http-bio-8080-exec-7,5, main] คลิกที่หน้า UI บางหน้าและตรวจสอบจุดแก้ปัญหา
Shailendra Singh

นอกจากนี้แม้ว่าในชื่อเธรดจะแสดงรายละเอียด 'main' แต่การเรียก setDaemon (true) บนวัตถุเธรดจะทำให้ daemon
Shailendra Singh

คุณไม่ได้อ่านส่วนที่ดี ... ฉันไม่ได้สงสัย (สมบูรณ์) เกี่ยวกับการเป็นภูตฉันกำลังบอกว่าคุณไม่สามารถสร้างความแตกต่างกับภูตด้ายอื่น ๆ เช่นนี้
AxelH

ใส่วิธีอื่น: เธรดหลักอาจเป็นเธรด daemon แต่ไม่ใช่ทุกเธรด daemon ที่เป็นเธรดหลัก (การระบุเธรดหลักคือสิ่งที่ถูกถามที่นี่)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.