AsyncTask เธรดไม่มีวันตาย


112

ฉันใช้AsyncTasks เพื่อดึงข้อมูลเพื่อตอบสนองต่อการที่ผู้ใช้กดปุ่ม สิ่งนี้ใช้งานได้ดีและช่วยให้อินเทอร์เฟซตอบสนองในขณะที่ดึงข้อมูล แต่เมื่อฉันตรวจสอบสิ่งที่เกิดขึ้นในดีบักเกอร์ Eclipse ฉันพบว่าทุกครั้งที่มีการสร้างใหม่AsyncTask(ซึ่งค่อนข้างบ่อยเพราะสามารถใช้ได้เพียงครั้งเดียว ) กำลังสร้างเธรดใหม่ แต่ไม่เคยยุติ

ผลลัพธ์คือมีAsyncTaskเธรดจำนวนมากเพียงแค่นั่งอยู่ที่นั่น ฉันไม่แน่ใจว่านี่เป็นปัญหาในทางปฏิบัติหรือไม่ แต่ฉันอยากจะกำจัดเธรดพิเศษเหล่านั้นออกไป

ฉันจะฆ่าเธรดเหล่านี้ได้อย่างไร


คำว่า "ไม่สิ้นสุด" หมายความว่าอย่างไร งานไม่สิ้นสุดเมธอด doInbackground หรือคุณแค่เห็นอ็อบเจ็กต์ asynctask ในตัวติดตามการจัดสรร?
Francesco Laurita

7
doInBackgroundวิธีการเสร็จสมบูรณ์ แต่ด้ายยังคงแสดงขึ้นมาในหน้าต่างแก้ไขข้อบกพร่อง ตัวอย่างเช่น: Thread [<23> AsyncTask #4](Running)
Computerish

คำตอบ:


202

AsyncTaskจัดการเธรดพูลที่สร้างขึ้นด้วยThreadPoolExecutor. จะมีตั้งแต่ 5 ถึง 128 เธรด หากมีมากกว่า 5 เธรดเธรดพิเศษเหล่านั้นจะติดอยู่ประมาณ 10 วินาทีก่อนที่จะถูกลบออก (หมายเหตุ: ตัวเลขเหล่านี้ใช้สำหรับรหัสโอเพนซอร์สที่มองเห็นได้ในปัจจุบันและแตกต่างกันไปตามรุ่นของ Android)

กรุณาปล่อยให้AsyncTaskกระทู้เดียว


ขอบคุณสำหรับคำอธิบาย! ฉันดีใจที่รู้ว่าฉันไม่ได้ทำอะไรผิด ด้วยความอยากรู้ว่าทำไมถึงออกแบบมาแบบนั้น? ทำไมไม่จบเธรดหลังจากที่วิธีการทั้งหมดกลับมาแล้ว?
Computerish

7
น่าจะช่วยประหยัดเวลาในการส่งเธรดในการร้องขอในภายหลัง
CommonsWare

@CommonsWare ฉันมีบริการที่ฉันใช้งาน AsyncTask เพื่อดำเนินการบางอย่างและบริการเริ่มต้นเมื่อกดปุ่มวิดเจ็ตและเมื่องานเสร็จสิ้นจะต้องหยุดบริการทันที แต่บางครั้ง AsyncTask ก็ไม่ตายดังนั้นคุณสามารถทำได้ บอกฉันว่าฉันจะหยุดมันได้อย่างไร
ล่า

1
@SreekanthKarumanaghat: การใช้AsyncTaskสิ่งที่ต้องใช้เวลานานนั้นเป็นความคิดที่ไม่ดีโดยทั่วไป แต่ไม่ความคิดเห็นของฉันเกี่ยวกับเธรดพิเศษที่กำลังจะหายไปคือเมื่อพวกเขาไม่ได้ใช้งาน ดังนั้นเมื่องานใดงานหนึ่งใน 6 งานของคุณสิ้นสุดลงเธรดจะยังคงอยู่ในพูลเป็นเวลา 10 วินาทีหลังจากนั้นเธรดนั้นจะถูกยกเลิก
CommonsWare

1
@SreekanthKarumanaghat: "คำถามของฉันคือมีข้อ จำกัด ในการรัน AsyncTasks ใน Parallel หรือไม่" - การใช้ประโยชน์อย่างมีนัยสำคัญในAsyncTaskปัจจุบันไม่ใช่แผนการที่ดี การมี 20+ ที่อาจทำงานเป็นเวลา 10+ วินาทีเป็นสิ่งที่ไม่ควรตรวจสอบโค้ด หากคุณสร้างงาน 20 อย่างต่อเนื่องกันจะมีเพียงไม่กี่งานเท่านั้นที่จะทำงานพร้อมกันและส่วนที่เหลือจะเข้าคิวเพื่อดำเนินการในภายหลัง จำนวนที่จะทำงานพร้อมกันขึ้นอยู่กับจำนวนคอร์ของ CPU AFAIK อัลกอริทึมปัจจุบันคือเธรดคู่ขนาน 2N + 1 โดยที่ N คือจำนวนคอร์
CommonsWare

24

นอกเหนือจากการตอบสนองของ CommonsWare:

ขณะนี้ฉันใช้ Android 2.2 และแอปพลิเคชันของฉันใช้ AsyncTask ไม่เกินหนึ่งรายการในเวลาใดก็ได้ แต่ฉันกำลังสร้างขึ้นใหม่ทุกๆ x นาที ในตอนแรก AsyncTask เธรดใหม่จะเริ่มปรากฏขึ้น (เธรดใหม่สำหรับ AsyncTask ใหม่) แต่หลังจาก 5 เธรด (ตามที่ CommonsWare กล่าวถึง) พวกเขาจะยังคงปรากฏอยู่ในหน้าต่างดีบักและจะถูกนำมาใช้ใหม่เมื่อจำเป็นต้องใช้เธรด AsyncTask ใหม่ พวกเขาจะอยู่ที่นั่นจนกว่าดีบักเกอร์จะตัดการเชื่อมต่อ


2
ใช่ยืนยัน: ฉันเห็น AsyncTasks ไม่เกิน 5 รายการ
Seraphim

3

อาการเดียวกันที่นี่. ในกรณีของฉันเธรดแขวนคออยู่หลังจากฉันฆ่ากิจกรรมและฉันหวังว่าแอปจะปิดอย่างสมบูรณ์ ปัญหาส่วนหนึ่งแก้ไขได้โดยใช้ตัวดำเนินการเธรดเดียว:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

สิ่งนี้ทำให้ด้ายหายไปหลังจากเสร็จสิ้นการทำงาน


คำตอบนี้ทำให้ AsyncTask หายไปหลังจากที่มันทำงานอาจจะไม่ใช่ "วิธีทำของ Google" แต่มันทำให้งานลุล่วง ขอบคุณ.
Henrique de Sousa

สิ่งนี้ช่วยแก้ปัญหาเฉพาะของฉันเกี่ยวกับการเรียกใช้ Asynctasks บนเธรดเดียว
กฎหมาย Gimenez

0

ใช้ThreadPoolExecutor

BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

โพสต์Runnableงานของคุณโดยใช้ เมธอดexecute ()

void execute (Runnable command)

ดำเนินการงานที่กำหนดในอนาคต งานอาจดำเนินการในเธรดใหม่หรือในเธรดรวมที่มีอยู่

เกี่ยวกับคำถามที่สองของคุณ:

ฉันจะฆ่าเธรดเหล่านี้ได้อย่างไร

เมื่อคุณทำงานทั้งหมดเสร็จแล้วThreadPoolExecutorให้ปิดเครื่องอย่างถูกต้องตามที่ระบุไว้ในโพสต์ด้านล่าง:

วิธีการปิด java ExecutorService อย่างถูกต้อง

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