Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách dùng take() trong PriorityBlockingQueue Android

PriorityBlockingQueue và take()

PriorityBlockingQueue là hàng đợi không giới hạn dung lượng (unbounded), sắp xếp các phần tử theo thứ tự ưu tiên (theo natural ordering hoặc Comparator). Khác với ArrayBlockingQueue, nó không block khi thêm phần tử (vì unbounded), nhưng take() vẫn block khi queue rỗng.

Bước 1: Tạo dự án mới

Khởi tạo project Android Studio.

Bước 2: Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/actionEvent"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginTop="30dp"
        android:textSize="30sp" />

</LinearLayout>

Bước 3: MainActivity.java

package com.example.myapplication;

import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import java.util.concurrent.PriorityBlockingQueue;

public class MainActivity extends AppCompatActivity {
    private PriorityBlockingQueue<String> priorityBlockingQueue;
    private TextView actionEvent;
    
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        priorityBlockingQueue = new PriorityBlockingQueue<>();
        actionEvent = findViewById(R.id.actionEvent);
        
        // Thêm các phần tử - String sắp xếp theo alphabet (natural ordering)
        priorityBlockingQueue.add("sai");
        priorityBlockingQueue.add("ram");
        priorityBlockingQueue.add("krishna");
        priorityBlockingQueue.add("prasad");
        priorityBlockingQueue.add("ram"); // Cho phép trùng lặp
        
        actionEvent.setText("Queue: " + priorityBlockingQueue);
        
        actionEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    // take() lấy phần tử có ưu tiên CAO NHẤT (theo alphabet: "krishna" < "prasad" < "ram" < "sai")
                    String head = priorityBlockingQueue.take();
                    actionEvent.setText("Taken: " + head + "\nRemaining: " + priorityBlockingQueue);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    actionEvent.setText("Interrupted: " + e.getMessage());
                }
            }
        });
    }
}

Kết quả chạy (String natural ordering = alphabet)

Ban đầu: [krishna, prasad, ram, ram, sai] (đã tự sắp xếp)

Click 1: Taken: krishna\nRemaining: [prasad, ram, ram, sai]

Click 2: Taken: prasad\nRemaining: [ram, ram, sai]

Click 3: Taken: ram\nRemaining: [ram, sai]

Tùy chỉnh thứ tự ưu tiên với Comparator

// Ưu tiên theo độ dài chuỗi (ngắn trước)
PriorityBlockingQueue<String> queue = new PriorityBlockingQueue<>(10, (a, b) -> 
    Integer.compare(a.length(), b.length())
);

// Hoặc object tùy chỉnh
class Task implements Comparable<Task> {
    int priority; // 1 = cao nhất
    String name;
    
    @Override
    public int compareTo(Task other) {
        return Integer.compare(this.priority, other.priority);
    }
}

PriorityBlockingQueue<Task> taskQueue = new PriorityBlockingQueue<>();
taskQueue.add(new Task(3, "Low priority"));
taskQueue.add(new Task(1, "High priority"));
taskQueue.add(new Task(2, "Medium priority"));

// take() sẽ trả về "High priority" trước

Đặc điểm quan trọng

  • Unbounded: Không bao giờ đầy, put()/offer() không bao giờ block
  • Thread-safe: An toàn cho multiple producers/consumers
  • Không đảm bảo thứ tự FIFO cho cùng priority: Phần tử cùng priority có thể lấy ra bất kỳ thứ tự nào
  • Iterator không theo thứ tự ưu tiên: iterator() duyệt theo nội bộ, không theo priority
  • Null không được phép: Ném NullPointerException

So sánh với PriorityQueue

Đặc điểm PriorityQueue PriorityBlockingQueue
Thread-safe Không Có
Blocking take() Không (ném exception) Có
Dung lượng Unbounded Unbounded
Sử dụng Single-thread Multi-thread

⚠️ Cảnh báo tương tự

Không gọi take() trên UI thread! Sẽ block main thread gây ANR. Dùng background thread.