ภาพรวมของ 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 extendsTextViewactionEvent→TextView actionEvent- เพิ่ม Generic Type
<String> - โค้ดต้นฉบับใช้
isEmpty()แต่ Title บอกsize()→ ปรับให้ใช้size()
⚠️ ข้อสำคัญ: size() เป็น O(n) ไม่ใช่ O(1)
⚠️ ประสิทธิภาพ: ConcurrentLinkedQueue.
เหตุผล: เป็น Lock-free queue ไม่มีตัวนับกลาง (Central counter) เพื่อหลีกเลี่ยง Contention
size() ต้อง เดินนับทุกโหนด (Traversal) เป็น O(n) ไม่ใช่เก็บตัวนับไว้เหตุผล: เป็น Lock-free queue ไม่มีตัวนับกลาง (Central counter) เพื่อหลีกเลี่ยง Contention
เปรียบเทียบ size() ใน Queue ต่างๆ
| Queue | size() Complexity | Thread-safe | Blocking |
|---|---|---|---|
| ConcurrentLinkedQueue | O(n) - Traversal | ✅ Lock-free | ไม่ |
| LinkedBlockingQueue | O(1) - Atomic counter | ✅ Lock-based | ใช่ |
| ArrayBlockingQueue | O(1) - Counter | ✅ Lock-based | ใช่ |
| PriorityBlockingQueue | O(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; }
}
วิธีทดสอบ
- รันแอป ดูคิว: [sai, ram, krishna, prasad, ram] (5 items)
- คลิก TextView → แสดง "Size: 5"
- ลองเพิ่ม/ลบข้อมูลแล้วเช็ค 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)