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

Cách sử dụng size() trong ConcurrentLinkedQueue trên Android

Giới thiệu về size() trong ConcurrentLinkedQueue

size() trả về số phần tử hiện có trong queue. Tuy nhiên, với ConcurrentLinkedQueue, phương thức này có hành vi đặc biệt cần lưu ý.

⚠️ Lưu ý QUAN TRỌNG về size()

ConcurrentLinkedQueue.size() không phải là O(1) - nó là O(n)!

  • Phải duyệt toàn bộ linked list để đếm
  • KHÔNG phải atomic snapshot - kết quả có thể lỗi thời ngay lập tức
  • Trong môi trường concurrent, kết quả chỉ mang tính tham khảo

Ví dụ minh họa (Code gốc có lỗi logic)

Code gốc gọi isEmpty() thay vì size():

actionEvent.setOnClickListener(v -> {
    // Code gốc sai - gọi isEmpty() không phải size()
    actionEvent.setText("" + concurrentLinkedQueue.isEmpty());
});

Code sửa đúng - demo size()

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.ConcurrentLinkedQueue;

public class MainActivity extends AppCompatActivity {
    ConcurrentLinkedQueue<String> concurrentLinkedQueue;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        concurrentLinkedQueue = new ConcurrentLinkedQueue<>();
        final TextView actionEvent = findViewById(R.id.actionEvent);

        concurrentLinkedQueue.add("sai");
        concurrentLinkedQueue.add("ram");
        concurrentLinkedQueue.add("krishna");
        concurrentLinkedQueue.add("prasad");
        concurrentLinkedQueue.add("ram");

        actionEvent.setText("Queue: " + concurrentLinkedQueue + "\nSize: " + concurrentLinkedQueue.size());

        actionEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Hiển thị size hiện tại
                int size = concurrentLinkedQueue.size();
                actionEvent.setText("Size: " + size + "\nQueue: " + concurrentLinkedQueue);
            }
        });
    }
}

Kết quả

Ban đầu: Size: 5\nQueue: [sai, ram, krishna, prasad, ram]

Click: Hiển thị size hiện tại (5, không thay đổi vì không xóa)

size() vs isEmpty()

Tại sao size() không atomic?

// Internal implementation (simplified)
public int size() {
    int count = 0;
    for (Node<E> p = first(); p != null; p = p.next) {
        if (p.item != null) count++;
    }
    return count;
}
// Trong lúc duyệt, thread khác có thể add/remove -> count không chính xác

Best Practices

  • Kiểm tra rỗng: Dùng isEmpty() thay vì size() == 0
  • Không dùng size() trong loop condition: while (queue.size() > 0) - sai!
  • Dùng poll() trong loop: while (queue.poll() != null) { ... }
  • Cần size chính xác: Sync external hoặc dùng collection khác

So sánh với các Queue khác

Phương thức Phức tạp Atomic Khuyến nghị
size() O(n) - duyệt list Không Tránh dùng trong hot path
isEmpty() O(1) - check head == null Có (tương đối) Dùng để check rỗng
Queue size() isEmpty() Thread-safe
ConcurrentLinkedQueue O(n) - không atomic O(1) Lock-free
ArrayBlockingQueue O(1) - atomic O(1) ReentrantLock
LinkedBlockingQueue O(1) - atomic O(1) ReentrantLock
PriorityBlockingQueue O(1) - atomic O(1) ReentrantLock

Khi nào dùng ConcurrentLinkedQueue?

  • High-throughput, low-latency
  • Non-blocking algorithms
  • Work-stealing queues
  • Event bus, message passing
  • KHÔNG cần size() chính xác realtime