Trong bài viết này, chúng ta sẽ cùng tìm hiểu về lớp ArrayBlockingQueue trong Java và các phương thức của nó cùng với sự trợ giúp của ví dụ dẫn chứng.
Lớp ArrayBlockingQueue
Lớp ArrayBlockingQueue của Collections Franework cung cấp việc triển khai BlockingQueue bằng cách sử dụng một mảng. Nó thực hiện triển khai cho BlockingQueue Interface.
Tạo ArrayBlockingQueue
Để tạo một ArrayBlockingQueue, chúng ta phải thêm gói package java.util.concurrent.ArrayBlockingQueue. Sau khi chúng ta thêm gói, sau đây là cách chúng ta có thể tạo một ArrayBlockingQueue trong Java:
1 |
ArrayBlockingQueue<Type> a = new ArrayBlockingQueue<>(int capacity); |
Trong đó:
- Type là kiểu dữ liệu.
- Capacity là kích thước của hàng đợi.
Chú ý: Bắt buộc phải truyền tham số Capacity.
Các phương thức của ArrayBlockingQueue
Lớp ArrayBlockingQueue cung cấp việc triển khai tất cả các phương thức trong BlockingQueue. Các phương thức này được sử dụng để chèn, truy cập và xóa các phần tử khỏi hàng đợi. Ngoài ra, chúng ta sẽ tìm hiểu về hai phương thức put() và take().
1. Chèn phần tử
- Phương thức add(): Chèn phần tử được chỉ định vào ArrayBlockingQueue. Nó sẽ đưa ra một ngoại lệ nếu hàng đợi đã đầy.
- Phương thức offer(): Chèn phần tử được chỉ định vào ArrayBlockingQueue. Nó trả về false nếu hàng đợi đã đầy.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 |
import java.util.concurrent.ArrayBlockingQueue; class Main { public static void main(String[] args) { ArrayBlockingQueue<String> sinh_vien = new ArrayBlockingQueue<>(5); sinh_vien.add("Sinh vien y"); sinh_vien.add("Sinh vien luat"); sinh_vien.offer("Sinh vien ky thuat"); System.out.println(sinh_vien); } } |
Kết quả:
1 |
[Sinh vien y, Sinh vien luat, Sinh vien ky thuat] |
2. Truy cập các phần tử
- Phương thức peek(): Trả về một phần tử từ phía trước của hàng đợi. Nó trả về null nếu hàng đợi trống rỗng.
- Phương thức iterator(): Trả về một đối tượng vòng lặp để truy cập tuần tự các phần tử. Nó sẽ đưa ra một ngoại lệ nếu hàng đợi trống rỗng. Chúng ta phải thêm gói package java.util.Iterator để sử dụng.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.concurrent.ArrayBlockingQueue; import java.util.Iterator; class Main { public static void main(String[] args) { ArrayBlockingQueue<String> sinh_vien = new ArrayBlockingQueue<>(5); sinh_vien.add("Sinh vien y"); sinh_vien.add("Sinh vien luat"); sinh_vien.offer("Sinh vien ky thuat"); String a = sinh_vien.peek(); System.out.println(a); Iterator<String> phan_tu = sinh_vien.iterator(); while(phan_tu.hasNext()) { System.out.print(phan_tu.next()); System.out.print("; "); } } } |
Kết quả:
1 2 |
Sinh vien y Sinh vien y; Sinh vien luat; Sinh vien ky thuat; |
3. Xóa các phần tử
- Phương thức remove(): Trả về và xóa một phần tử được chỉ định khỏi hàng đợi. Nó sẽ đưa ra một ngoại lệ nếu hàng đợi trống rỗng.
- Phương thức poll(): Trả về và xóa một phần tử được chỉ định khỏi hàng đợi. Nó trả về null nếu hàng đợi trống rỗng.
- Phương thức clear(): Loại bỏ tất cả các phần tử khỏi hàng đợi.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import java.util.concurrent.ArrayBlockingQueue; import java.util.Iterator; class Main { public static void main(String[] args) { ArrayBlockingQueue<String> sinh_vien = new ArrayBlockingQueue<>(5); sinh_vien.add("Sinh vien y"); sinh_vien.add("Sinh vien luat"); sinh_vien.offer("Sinh vien ky thuat"); System.out.println(sinh_vien); String a = sinh_vien.poll(); System.out.println(sinh_vien); sinh_vien.clear(); System.out.println(sinh_vien); } } |
Kết quả:
1 2 3 |
[Sinh vien y, Sinh vien luat, Sinh vien ky thuat] [Sinh vien luat, Sinh vien ky thuat] [] |
Phương thức put() và take()
Trong quá trình xử lý đa luồng, chúng ta có thể sử dụng put() và take() để chặn hoạt động của một luồng để đồng bộ hóa với một luồng khác. Các phương thức này sẽ đợi cho đến khi chúng được thực thi thành công.
Phương thức put()
Để thêm một phần tử vào cuối hàng đợi, chúng ta có thể sử dụng phương thức put(). Nếu hàng đợi chặn mảng đã đầy, nó sẽ đợi cho đến khi có khoảng trống trong hàng đợi mảng để thêm một phần tử.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import java.util.concurrent.ArrayBlockingQueue; class Main { public static void main(String[] args) { ArrayBlockingQueue<String> sinh_vien = new ArrayBlockingQueue<>(5); try { sinh_vien.put("Sinh vien Y"); sinh_vien.put("Sinh vien Luat"); System.out.println(sinh_vien); } catch(Exception e) { System.out.println(e); } } } |
Kết quả:
1 |
[Sinh vien Y, Sinh vien Luat] |
Ở đây, phương thức put() có thể đưa ra một InterruptException nếu nó bị gián đoạn trong khi chờ đợi. Do đó, chúng ta phải đặt nó bên trong một khối try..catch.
Phương thức take()
Để trả về và loại bỏ một phần tử từ phía trước của hàng đợi, chúng ta có thể sử dụng phương thức take(). Nếu hàng đợi trống rỗng, nó sẽ đợi cho đến khi có các phần tử trong hàng đợi.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import java.util.concurrent.ArrayBlockingQueue; class Main { public static void main(String[] args) { ArrayBlockingQueue<String> sinh_vien = new ArrayBlockingQueue<>(5); try { sinh_vien.put("Sinh vien Y"); sinh_vien.put("Sinh vien Luat"); System.out.println(sinh_vien); String a = sinh_vien.take(); System.out.println(a); } catch(Exception e) { System.out.println(e); } } } |
Kết quả:
1 2 |
[Sinh vien Y, Sinh vien Luat] Sinh vien Y |
Ở đây, phương thức take() sẽ đưa ra một InterrupedException nếu nó bị gián đoạn trong khi chờ đợi. Do đó, chúng ta phải đặt nó bên trong một khối Try Catch.
Các phương thức khác
Phương thức | Mô tả |
contains(element) | Trả về true nếu tồn tại phần tử xác định trong hàng đợi và ngược lại trả về false. |
size() | Trả về kích thước. |
toArray() | Chuyển đổi hàng đợi sang dạng mảng. |
toString() | Chuyển đổi hàng đợi sang dạng chuỗi ký tự. |
Tại sao sử dụng ArrayBlockingQueue?
ArrayBlockingQueue sử dụng mảng làm bộ nhớ trong của nó. Nó được coi là một tập hợp an toàn cho luồng. Do đó, nó thường được sử dụng trong các ứng dụng đa luồng.
Giả sử, một luồng đang chèn các phần tử vào hàng đợi và một luồng khác đang xóa các phần tử khỏi hàng đợi. Nếu luồng đầu tiên chậm hơn luồng thứ hai, thì ArrayBlockingQueue có thể khiến luồng thứ hai đợi cho đến khi luồng đầu tiên hoàn thành xong các thao tác.
Trên đây là khái niệm và ví dụ cơ bản về lớp ArrayBlockingQueue trong Java. Hy vọng mọi người có thể áp dụng vào trong chương trình của mình. Mọi người hãy tiếp tục theo dõi các bài tiếp theo và cập nhật các bài tiếp theo trên tek4 nhé!
P/s: Cảm ơn mọi người!