12/08/2018, 13:23

Sending Operations to Multiple Threads

Tốc độ và hiệu quả của 1 tiến trình kéo dài, hay những hoạt động dữ liệu chuyên sâu thường sẽ được cải thiện khi bạn tách nhỏ thành những operator trên nhiều threads khác nhau. Trên những thiết bị mà có bộ vi xử lý nhiều lõi. Hệ thống có thể chạy nhiều tiến trình song song thay vì chạy lần lượt ...

Tốc độ và hiệu quả của 1 tiến trình kéo dài, hay những hoạt động dữ liệu chuyên sâu thường sẽ được cải thiện khi bạn tách nhỏ thành những operator trên nhiều threads khác nhau. Trên những thiết bị mà có bộ vi xử lý nhiều lõi. Hệ thống có thể chạy nhiều tiến trình song song thay vì chạy lần lượt từng tiến trình. Một ví dụ đơn giản là việc decode nhiều ảnh để hiển thị trên thumbnail screen sẽ nhanh hơn đáng kể nếu bạn thực hiện decode trên 1 luồng đơn. Bài viết này sẽ hướng dẫn cách thiết lâp và sử dụng multiple thread trên android app, sử dụng thread pool object. Bạn cũng sẽ tìm hiểu làm thế nào để xác định code chạy trên 1 thread và làm thế nào để giao tiếp giữa 1 thread khác và main thread.

Tạo 1 lớp thực hiện 1 runable đơn giản:

public class PhotoDecodeRunnable implements Runnable {
    ...
    @Override
    public void run() {
        /*
         * Code you want to run on the thread goes here
         */
        ...
    }
    ...
}

Method Runable.run() chứa đoạn code thực thi. Thông thường mọi thứ đều được cho phép trong runable. Vì Runable không thể chạy trên UI Thread nên nó không thể chỉnh sửa trực tiếp dữ liệu trên UIthread. Để giao tiếp với UIthread người ta phải dùng đêns Handler (Sẽ giới thiệu ở phần sau). Khi method run bắt đầu chạy. Thiết lập để các quyền để set ưu tiên background bằng cách hoik Process.setThreadPriority () với THREAD_PRIORITY_BACKGROUND. Cách tiệp cận này làm giải sự cạnh tranh tài nguyên giữa các object thread và UI thread!

class PhotoDecodeRunnable implements Runnable {
...
    /*
     * Defines the code to run for this task.
     */
    @Override
    public void run() {
        // Moves the current Thread into the background
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
        ...
        /*
         * Stores the current Thread in the PhotoTask instance,
         * so that the instance
         * can interrupt the Thread.
         */
        mPhotoTask.setImageDecodeThread(Thread.currentThread());
        ...
    }
...
}

Để tự động chạy các task mỗi khi sẵn sàng, bạn cần cung cấp 1 collections quản lý các thread. Để làm điều này, sử dụng 1 instance cuar ThreadPoolExecutor, cho phép chạy 1 task từ trong queue khi 1 thread của pool được giải phóng, để chay 1 task, bạn luôn luôn phải add nó vào trong queue. 1 thread pull có thể chạy nhiều instance song song của task. Vì vậy bạn phải đảm bảo code của bạn là 1 thread an toàn. 1 biến có thể access bởi nhiều hơn 1 thread sẽ dẫn đến tình trạng bạn có thể đọc 1 biến đang được ghi giá trị. Những trường hợp này thường rơi vào static, tuy nhiên vẫn có thể rơi vào những trường hợp object được tạo 1 lần.

Tạo instance threadpool trong class.

public class PhotoManager {
    ...
    static  {
        ...
        // Creates a single static instance of PhotoManager
        sInstance = new PhotoManager();
    }
    ...

sử dụng phương thức khởi tạo private

public class PhotoManager {
    ...
    /**
     * Constructs the work queues and thread pools used to download
     * and decode images. Because the constructor is marked private,
     * it's unavailable to other classes, even in the same package.
     */
    private PhotoManager() {
    ...
    }

Start method của bạn bằng cách gọi hàm trong threadpool class. public class PhotoManager { ... // Called by the PhotoView to get a photo static public PhotoTask startDownload( PhotoView imageView, boolean cacheFlag) { ... // Adds a download task to the thread pool for execution sInstance. mDownloadThreadPool. execute(downloadTask.getHTTPDownloadRunnable()); ... } Instantiate 1 Handler trong app để thao tác với UI.

private PhotoManager() {
    ...
        // Defines a Handler object that's attached to the UI thread
        mHandler = new Handler(Looper.getMainLooper()) {
            /*
             * handleMessage() defines the operations to perform when
             * the Handler receives a new Message to process.
             */
            @Override
            public void handleMessage(Message inputMessage) {
                ...
            }
        ...
        }
    }

Như vậy qua bài số 1 của loạt bài về multi thread bạn có thể hiểu được phần nào các khái niệm Task, multi task... Việc quản lý task trong application đôi khi đóng vai trò trọng yếu, vì vậy hi vọng bài viết có thể giúp các developer trong việc quản lý tiến trình trong application.

0