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

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

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ùng take()
  • 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...).