Trong bài viết này, chúng ta sẽ cùng tìm hiểu về BlockingQueue Interface trong Java và các phương thức của nó cùng với ví dụ dẫn chứng.
BlockingQueue Interface
BlockingQueue Interface của Collections Framework kế thừa Queue Interface. Nó cho phép bất kỳ hoạt động nào cũng sẽ phải chờ đợi cho đến khi nó có thể được thực hiện thành công.
Ví dụ, nếu chúng ta muốn xóa một phần tử khỏi hàng đợi đang trống rỗng, thì hàng đợi sẽ cho phép thao tác xóa chờ cho đến khi hàng đợi chứa một phần tử hoặc nhiều phần tử để có thể thực hiện việc xóa.
Các lớp triển khai BlockingQueue
Vì BlockingQueue là một Interface, chúng ta không thể cung cấp việc triển khai trực tiếp cho nó.
Để sử dụng chức năng của BlockingQueue, chúng ta cần sử dụng các lớp triển khai.
- ArrayBlockingQueue
- LinkedBlockingQueue
Làm thế nào để sử dụng BlockingQueue?
Chúng ta phải thêm gói package java.util.concurrent.BlockingQueue để sử dụng BlockingQueue. Sau đây là cách mà ta có thể khởi tạo BlockingQueue.
1 |
BlockingQueue <Integer> a = new ArraryBlockingQueue<>(); |
Ở đây, chúng ta đã tạo đối tượng a của các lớp ArrayBlockingQueue. Đối tượng này có thể sử dụng các chức năng của BlockingQueue Interface.
Các phương thức BlockingQueue
Dựa trên việc hàng đợi đầy hay trống rỗng, các phương thức của BlockingQueue có thể được chia thành 3 loại:
- Phương thức add(): Chèn một phần tử ở cuối hàng đợi. Đưa ra một ngoại lệ nếu hàng đợi đã đầy.
- Phương thức element(): Trả về phần đầu của hàng đợi. Đưa ra một ngoại lệ nếu hàng đợi trống rỗng.
- Phương thức remove(): Loại bỏ một phần tử khỏi hàng đợi. Đưa ra một ngoại lệ nếu hàng đợi trống rỗng.
1. Các phương thức trả về giá trị
- Phương thức offer(): Chèn phần tử được chỉ định vào cuối hàng đợi. Trả về false nếu hàng đợi đã đầy.
- Phương thức peek(): Trả về phần đầu của hàng đợi. Trả về null nếu hàng đợi trống rỗng.
- Phương thức poll(): Loại bỏ một phần tử khỏi hàng đợi. Trả về null nếu hàng đợi trống rỗng.
Phương thức offer() và poll() có thể được sử dụng với thời gian chờ. Tức là, chúng ta có thể truyền giá trị thời gian làm tham số.
Ví dụ:
1 |
offer(a, 5432, milliseconds) |
Trong đó:
- a là phần tử được chèn vào hàng đợi
- Và chúng ta đã đặt thời gian chờ là 5432 milliseconds. Điều này có nghĩa là phương thức offer() sẽ cố gắng chèn một phần tử vào hàng đợi trong 5432 milliseconds. Nếu phần tử không thể được chèn trong thời gian xác định này, phương thức sẽ trả về false.
Chú ý: Thay vì milliseconds, chúng ta cũng có thể sử dụng các đơn vị thời gian sau: days, hours, minutes, seconds, microseconds và nanoseconds trong phương thức offer() và poll().
2. Các phương thức chặn thao tác
BlockingQueue cũng cung cấp các phương thức để chặn các hoạt động và đợi nếu hàng đợi đầy hoặc trống rỗng.
- Phương thức put(): Chèn một phần tử vào hàng đợi. Nếu hàng đợi đầy, nó sẽ đợi cho đến khi hàng đợi có khoảng trống để chèn một phần tử.
- Phương thức take(): Loại bỏ và trả về một phần tử từ hàng đợi. Nếu hàng đợi trống, nó sẽ đợi cho đến khi hàng đợi có các phần tử.
Giả sử, chúng ta muốn chèn các phần tử vào một hàng đợi. Nếu hàng đợi đầy thì phương thức put() sẽ đợi cho đến khi hàng đợi có khoảng trống để chèn các phần tử.
Tương tự, nếu chúng ta muốn xóa các phần tử khỏi hàng đợi. Nếu hàng đợi trống rỗng thì phương thức take() sẽ đợi cho đến khi hàng đợi chứa phần tử.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import java.util.concurrent.BlockingQueue; import java.util.concurrent.ArrayBlockingQueue; class Main { public static void main(String[] args) { BlockingQueue<Integer> so_nguyen = new ArrayBlockingQueue<>(5); try { so_nguyen.put(100); so_nguyen.put(85); so_nguyen.put(56); System.out.println(so_nguyen); int a = so_nguyen.take(); System.out.println(a); System.out.println(so_nguyen); } catch(Exception e) { e.getStackTrace(); } } } |
Kết quả:
1 2 3 |
[100, 85, 56] 100 [85, 56] |
Tại sao phải sử dụng BlockingQueue?
Trong Java, BlockingQueue được coi là một tập hợp an toàn cho thực thi củ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ạy chậm hơn, thì BlockingQueue có thể chặn luồng thứ hai và bắt nó đợi cho đến khi luồng đầu tiên hoàn thành xong thao tác.
Trên đây là khái niệm và ví dụ cơ bản về BlockingQueue Interface 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 mới nhất trên tek4 nhé!
P/s: Cảm ơn mọi người!