Các chuỗi AsyncTask không bao giờ chết


112

Tôi đang sử dụng AsyncTask s để tìm nạp dữ liệu khi người dùng nhấn một nút. Điều này hoạt động tốt và giữ cho giao diện luôn phản hồi trong khi tìm nạp dữ liệu, nhưng khi tôi kiểm tra những gì đang diễn ra trong trình gỡ lỗi Eclipse, tôi phát hiện ra rằng mỗi lần một cái mới AsyncTaskđược tạo (khá thường xuyên, vì chúng chỉ có thể được sử dụng một lần ), một chủ đề mới đang được tạo nhưng chưa bao giờ kết thúc.

Kết quả là một số lượng lớn AsyncTask chủ đề chỉ nằm ở đó. Tôi không chắc đây có phải là vấn đề trong thực tế hay không, nhưng tôi thực sự muốn loại bỏ những chủ đề thừa đó.

Làm thế nào tôi có thể giết những chủ đề này?


Bạn có nghĩa là gì với "không bao giờ chấm dứt"? Tác vụ không bao giờ kết thúc phương thức doInbackground của nó hay bạn chỉ thấy đối tượng asynctask trong trình traker cấp phát?
Francesco Laurita

7
Các doInBackgroundphương pháp hoàn tất, nhưng các chủ đề tiếp tục xuất hiện trong cửa sổ gỡ lỗi. Ví dụ: Thread [<23> AsyncTask #4](Running)
Computerish

Câu trả lời:


202

AsyncTask quản lý một nhóm chủ đề, được tạo bằng ThreadPoolExecutor . Nó sẽ có từ 5 đến 128 chủ đề. Nếu có nhiều hơn 5 chủ đề, những chủ đề thừa đó sẽ tồn tại ít nhất 10 giây trước khi bị loại bỏ. (lưu ý: những số liệu này dành cho mã nguồn mở hiện có thể nhìn thấy và thay đổi theo bản phát hành Android).

Làm ơn để các AsyncTaskchủ đề một mình.


Cảm ơn vì lời giải thích! Tôi rất vui khi biết rằng mình không làm gì sai. Không khỏi tò mò, tại sao nó lại được thiết kế như vậy? Tại sao không chỉ kết thúc chủ đề sau khi tất cả các phương thức đã trả về?
Computerish

7
Có lẽ để tiết kiệm thời gian phân chia các chủ đề cho các yêu cầu sau này.
CommonsWare

@CommonsTôi có một dịch vụ trong đó tôi đang chạy AsyncTask để thực hiện một số hoạt động và dịch vụ bắt đầu khi nút widget đang được nhấn và khi tác vụ kết thúc, nó phải dừng servie ngay lập tức, nhưng đôi khi AsyncTask sẽ không chết, bạn có thể không cho tôi biết làm thế nào để tôi ngăn chặn nó
Hunt

1
@SreekanthKarumanaghat: Sử dụng một AsyncTaskcho một thứ gì đó sẽ mất nhiều thời gian nói chung là một ý kiến ​​tồi. Nhưng không, nhận xét của tôi về các chủ đề thừa sẽ biến mất khi chúng không được sử dụng. Vì vậy, khi một trong 6 nhiệm vụ của bạn kết thúc, luồng của nó sẽ vẫn ở trong nhóm trong 10 giây, sau đó luồng đó sẽ được kết thúc.
CommonsWare

1
@SreekanthKarumanaghat: "Câu hỏi của tôi là liệu có bất kỳ hạn chế nào đối với việc chạy 20 (giả sử) AsyncTasks trong Song song không?" - tận dụng đáng kể AsyncTaskngày hôm nay không phải là một kế hoạch tuyệt vời. Có 20+ có thể chạy trong hơn 10 giây là loại điều không nên xem xét mã. Nếu bạn tạo 20 tác vụ liên tiếp nhanh chóng, chỉ một số tác vụ sẽ chạy cùng một lúc và số còn lại sẽ được xếp hàng để thực hiện sau. Số lượng sẽ chạy cùng một lúc dựa trên số lượng lõi của CPU. AFAIK, thuật toán hiện tại là 2N + 1 luồng song song, trong đó N là số lõi.
CommonsWare

24

Ngoài phản hồi của CommonsWare:

Hiện tại, tôi đang sử dụng Android 2.2 và ứng dụng của tôi không sử dụng nhiều hơn một AsyncTask bất cứ lúc nào, nhưng tôi sẽ tạo một AsyncTask mới sau mỗi x phút. Lúc đầu, các Chủ đề AsyncTask mới bắt đầu xuất hiện (một Chủ đề mới cho một AsyncTask mới) nhưng sau 5 luồng (như CommonsWare đã đề cập), chúng chỉ hiển thị trong cửa sổ gỡ lỗi và được sử dụng lại khi cần các luồng AsyncTask mới. Họ chỉ ở đó cho đến khi trình gỡ lỗi ngắt kết nối.


2
Có, đã xác nhận: Tôi thấy không quá 5 AsyncTasks.
Seraphim's

3

Cùng một triệu chứng ở đây. Trong trường hợp của tôi, các luồng vẫn tồn tại sau khi tôi giết Hoạt động và tôi hy vọng Ứng dụng sẽ đóng hoàn toàn. Vấn đề được giải quyết một phần bằng cách sử dụng trình thực thi một luồng:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Điều này làm cho sợi chỉ biến mất sau khi hoàn thành công việc của nó.


Câu trả lời này đã khiến AsyncTask biến mất sau khi nó chạy, có thể nó không phải là "cách hoạt động của google" nhưng nó sẽ hoàn thành công việc. Cảm ơn bạn.
Henrique de Sousa

Điều này đã giải quyết vấn đề cụ thể của tôi liên quan đến việc chạy Asynctasks trên một luồng duy nhất.
Law Gimenez

0

Sử dụng 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);

Đăng Runnablenhiệm vụ của bạn bằng cách sử dụng phương thức execute () .

void execute (Runnable command)

Thực thi nhiệm vụ đã cho vào một lúc nào đó trong tương lai. Tác vụ có thể thực thi trong một chuỗi mới hoặc trong một chuỗi tổng hợp hiện có

Về truy vấn thứ hai của bạn:

Làm thế nào tôi có thể giết những chủ đề này?

Khi bạn đã hoàn thành tất cả công việc của mình ThreadPoolExecutor, hãy tắt nó đúng cách như được trích dẫn trong bài đăng dưới đây:

Cách tắt java ExecutorService đúng cách

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.