ArrayBlockingQueue và phương thức take()
ArrayBlockingQueue là hàng đợi (queue) bị giới hạn dung lượng, dựa trên mảng, tuân theo nguyên tắc FIFO (First-In-First-Out). Phần tử đầu vào sớm nhất sẽ ở đầu hàng và bị lấy ra trước.
Phương thức take() lấy và xóa phần tử ở đầu hàng đợi. Nếu hàng đợi rỗng, nó sẽ block (chờ) cho đến khi có phần tử mới.
Bước 1: Tạo dự án mớ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.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import java.util.concurrent.ArrayBlockingQueue;
public class MainActivity extends AppCompatActivity {
private ArrayBlockingQueue<String> arrayBlockingQueue;
private TextView actionEvent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Dung lượng tối đa 50 phần tử
arrayBlockingQueue = new ArrayBlockingQueue<>(50);
actionEvent = findViewById(R.id.actionEvent);
// Thêm 4 phần tử
arrayBlockingQueue.add("sai");
arrayBlockingQueue.add("ram");
arrayBlockingQueue.add("krishna");
arrayBlockingQueue.add("prasad");
actionEvent.setText("Queue: " + arrayBlockingQueue);
actionEvent.setOnClickListener(new View.OnClickListener() {
@SuppressLint("SetTextI18n")
@Override
public void onClick(View v) {
try {
// take() block nếu queue rỗng - ở đây có dữ liệu nên trả về ngay
String head = arrayBlockingQueue.take();
actionEvent.setText("Taken: " + head + "\nRemaining: " + arrayBlockingQueue);
} catch (InterruptedException e) {
e.printStackTrace();
actionEvent.setText("Interrupted: " + e.getMessage());
}
}
});
}
}
Kết quả chạy
Ban đầu: Queue: [sai, ram, krishna, prasad]
Click 1 lần: Taken: sai\nRemaining: [ram, krishna, prasad]
Click 2 lần: Taken: ram\nRemaining: [krishna, prasad]
Click 4 lần: Queue rỗng, click tiếp theo sẽ block vô hạn cho đến khi có thread khác thêm phần tử.
Các phương thức liên quan quan trọng
| Phương thức | Hành vi khi queue rỗng | Hành vi khi queue đầy |
|---|---|---|
take() |
Block cho đến khi có phần tử | N/A (lấy phần tử) |
poll() |
Trả về null ngay lập tức | N/A |
poll(timeout, unit) |
Chờ timeout rồi trả null | N/A |
put(e) |
N/A | Block cho đến khi có chỗ |
offer(e) |
N/A | Trả về false ngay lập tức |
offer(e, timeout, unit) |
N/A | Chờ timeout rồi trả false |
Ứng dụng thực tế
- Producer-Consumer pattern: Thread producer dùng
put(), consumer dùngtake() - Thread pool task queue: Các task đợi được xử lý
- Message passing giữa threads: An toàn, block tự động
⚠️ Cảnh báo
Không bao giờ gọi take() trên UI thread (main thread)! Sẽ gây ANR (Application Not Responding) nếu queue rỗng. Luôn dùng background thread (ExecutorService, Thread, Coroutine, RxJava...).