Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีใช้ size() ใน ConcurrentLinkedQueue ของ Android

ภาพรวมของ ConcurrentLinkedQueue

ConcurrentLinkedQueue เป็นคิวแบบไม่มีขอบเขต (unbounded) บนโหนดเชื่อมโยง รองรับหลายเธรด (thread-safe) เรียงลำดับ FIFO เพิ่มที่ท้าย ไม่อนุญาตค่า null

ตัวอย่างการใช้งาน size()

ตัวอย่างนี้สาธิตเมธอด size() ซึ่งคืนจำนวนสมาชิกในคิว หมายเหตุ: การนับเป็น O(n) ไม่ใช่ O(1)

ขั้นตอนที่ 1-2: สร้างโปรเจกต์และ Layout

สร้างโปรเจกต์ใหม่ ใช้ Layout TextView

ขั้นตอนที่ 3: โค้ด 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.ConcurrentLinkedQueue;

public class MainActivity extends AppCompatActivity {  // แก้: MainActivityextends
    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);  // แก้: TextViewactionEvent
        
        concurrentLinkedQueue.add("sai");
        concurrentLinkedQueue.add("ram");
        concurrentLinkedQueue.add("krishna");
        concurrentLinkedQueue.add("prasad");
        concurrentLinkedQueue.add("ram");
        
        actionEvent.setText("" + concurrentLinkedQueue);
        
        actionEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // แสดงขนาดคิว
                actionEvent.setText("Size: " + concurrentLinkedQueue.size());
                // หรือตรวจสอบว่าว่าง: concurrentLinkedQueue.isEmpty()
            }
        });
    }
}

🔧 การแก้ไขจากต้นฉบับ

  • MainActivityextends → MainActivity extends
  • TextViewactionEvent → TextView actionEvent
  • เพิ่ม Generic Type <String>
  • โค้ดต้นฉบับใช้ isEmpty() แต่ Title บอก size() → ปรับให้ใช้ size()

⚠️ ข้อสำคัญ: size() เป็น O(n) ไม่ใช่ O(1)

⚠️ ประสิทธิภาพ: ConcurrentLinkedQueue.size() ต้อง เดินนับทุกโหนด (Traversal) เป็น O(n) ไม่ใช่เก็บตัวนับไว้
เหตุผล: เป็น Lock-free queue ไม่มีตัวนับกลาง (Central counter) เพื่อหลีกเลี่ยง Contention

เปรียบเทียบ size() ใน Queue ต่างๆ

Queuesize() ComplexityThread-safeBlocking
ConcurrentLinkedQueueO(n) - Traversal✅ Lock-freeไม่
LinkedBlockingQueueO(1) - Atomic counter✅ Lock-basedใช่
ArrayBlockingQueueO(1) - Counter✅ Lock-basedใช่
PriorityBlockingQueueO(1) - Counter✅ Lock-basedไม่ (unbounded)

แนวทางปฏิบัติที่ดี (Best Practices)

  • หลีกเลี่ยง size() ใน Hot path - ใช้ isEmpty() แทน (O(1) - เช็ค head pointer)
  • หากต้องการขนาดบ่อย ควรเก็บ Counter เอง (AtomicInteger) พร้อมกับ Queue
  • ใช้ isEmpty() สำหรับเช็คว่าง - เร็วกว่ามาก

ตัวอย่าง: Wrapper ที่มี Counter

public class SizedConcurrentLinkedQueue<E> {
    private final ConcurrentLinkedQueue<E> queue = new ConcurrentLinkedQueue<>();
    private final AtomicInteger size = new AtomicInteger(0);
    
    public boolean add(E e) {
        if (queue.add(e)) {
            size.incrementAndGet();
            return true;
        }
        return false;
    }
    
    public E poll() {
        E e = queue.poll();
        if (e != null) size.decrementAndGet();
        return e;
    }
    
    public int size() { return size.get(); }  // O(1)!
    public boolean isEmpty() { return size.get() == 0; }
}

วิธีทดสอบ

  1. รันแอป ดูคิว: [sai, ram, krishna, prasad, ram] (5 items)
  2. คลิก TextView → แสดง "Size: 5"
  3. ลองเพิ่ม/ลบข้อมูลแล้วเช็ค size() ใหม่

เมธอดที่เกี่ยวข้อง

// O(1) - เร็ว ใช้แทน size() == 0
boolean isEmpty()

// O(n) - ต้องเดินนับ
int size()

// Iterator - Weakly consistent
Iterator<E> iterator()

// To Array - O(n)
Object[] toArray()
T[] toArray(T[] a)