Trong hướng dẫn này, chúng ta sẽ tìm hiểu về BlockingQueue interface trong Java và các hàm của nó.

BlockingQueue interface của Collections framework trong Java mở rộng Queue interface. Nó cho phép mọi thao tác chờ cho đến khi có thể 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 một queue rỗng, thì BlockingQueue cho phép thao tác xóa chờ cho đến khi queue chứa một số phần tử để có thể bị xóa.

Các class triển khai BlockingQueue

Vì BlockingQueue là một interface, chúng ta không thể triển khai trực tiếp nó.

Để sử dụng chức năng của BlockingQueue, chúng ta cần sử dụng các class triển khai nó như:

  • ArrayBlockingQueue
  • LinkedBlockingQueue

1. Sử dụng các BlockingQueue như thế nào?

Chúng ta phải import gói java.util.concurrent.BlockingQueue để sử dụng BlockingQueue.

// Array implementation of BlockingQueue
BlockingQueue<String> animal1 = new ArraryBlockingQueue<>();

// LinkedList implementation of BlockingQueue
BlockingQueue<String> animal2 = new LinkedBlockingQueue<>();

Ở đây, chúng ta đã tạo ra các đối tượng Animal1 và Animal2 của các class tương ứng là ArrayBlockingQueue và LinkedBlockingQueue. Những đối tượng này có thể sử dụng các chức năng của BlockingQueue interface.

2. Các hàm của BlockingQueue

Dựa trên việc queue đã đầy hay trống, các hàm của BlockingQueue có thể được chia thành 3 loại:

3. Các hàm ném một ngoại lệ

  • add()- Chèn một phần tử vào BlockingQueue ở cuối queue. Ném một ngoại lệ nếu queue đã đầy.
  • element()- Trả về phần tử đầu của BlockingQueue. Ném một ngoại lệ nếu queue trống.
  • remove()- Loại bỏ một phần tử khỏi BlockingQueue. Ném một ngoại lệ nếu queue trống.

4. Các hàm trả về một số giá trị

  • offer()- Chèn phần tử được chỉ định vào BlockingQueue ở cuối queue. Trả về false nếu queue đầy.
  • peek()- Trả về phần tử đầu của BlockingQueue. Trả về null nếu queue trống.
  • poll()- Loại bỏ một phần tử khỏi BlockingQueue. Trả về null nếu queue trống.

4.1 Đọc thêm về hàm offer() và poll​​()

Các hàm offer()và poll() có thể được sử dụng với thời gian chờ. Đó là, chúng ta có thể vượt qua các đơn vị thời gian như một tham số. Ví dụ,

offer(value, 100, milliseconds)

Ở đây,

  • Value là phần tử được chèn vào queue
  • Và chúng ta đã đặt thời gian chờ là 100 mili giây

Điều này có nghĩa là hàm offer() sẽ cố gắng chèn một phần tử vào BlockingQueue trong thời gian 100  mili giây. Nếu phần tử không thể được chèn trong 100 mili giây, hàm sẽ trả về false.

Lưu ý: Thay vì milliseconds, chúng ta cũng có thể sử dụng các đơn vị thời gian: days, hours, minutes, seconds, microseconds và nanoseconds ở hàm offer() và poll().

4.2 Các hàm để chặn thao tác

Các BlockingQueue cũng cung cấp hàm để ngăn chặn lại việc thực hiện các thao tác và chờ nếu queue đầy hoặc rỗng.

  • put()- Chèn một phần tử vào BlockingQueue. Nếu queue đầy, nó sẽ đợi cho đến khi queue có khoảng trống để chèn một phần tử.
  • take()- Loại bỏ và trả về một phần tử từ BlockingQueue. Nếu queue trống, nó sẽ đợi cho đến khi queue có các phần tử để có thể xóa.

Giả sử, chúng ta muốn chèn các phần tử vào một queue. Nếu queue đó đầy thì hàm put()sẽ đợi cho đến khi queue 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 queue. Nếu queue trống thì hàm take() sẽ đợi cho đến khi queue chứa các phần tử để có thể xóa.

5. Triển khai BlockingQueue trong ArrayBlockingQueue

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;

class Main {

    public static void main(String[] args) {
      // Create a blocking queue using the ArrayBlockingQueue
      BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(5);

      try {
        // Insert element to blocking queue
        numbers.put(2);
        numbers.put(1);
        numbers.put(3);
        System.out.println("BLockingQueue: " + numbers);

        // Remove Elements from blocking queue
        int removedNumber = numbers.take();
        System.out.println("Removed Number: " + removedNumber);
      }

      catch(Exception e) {
          e.getStackTrace();
      }
    }
}

Kết quả

BlockingQueue: [2, 1, 3]
Removed Element: 2

Để tìm hiểu thêm về ArrayBlockingQueue, hãy truy cập ArrayBlockingQueue trong Java .

6. Tại sao nên chọn BlockingQueue?

Trong Java, BlockingQueue được coi là collection an toàn luồng . Đó là bởi vì nó có thể hữu ích trong các thao tác đa luồng.

Giả sử một luồng đang chèn các phần tử vào queue và một luồng khác đang xóa các phần tử khỏi queue.

Bây giờ, nếu luồng đầu tiên chạy chậm hơn, thì BlockingQueue có thể khiến luồng thứ hai chờ cho đến khi luồng đầu tiên hoàn thành thao tác.

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!