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.