2016-05-02 18 views
5

Tôi có kịch bản người tiêu dùng sản xuất nơi người sản xuất sản xuất nhanh hơn nhiều so với người tiêu dùng có thể tiêu thụ. Nói chung, giải pháp là làm cho khối nhà sản xuất kể từ khi kịch bản sản xuất/người tiêu dùng hoạt động nhanh như thành phần chậm nhất. Điều chỉnh hoặc ngăn chặn các nhà sản xuất là không phải là một giải pháp tốt vì ứng dụng của chúng tôi cung cấp đủ thời gian để người tiêu dùng bắt kịp sau này.Triển khai "Xếp hàng đợi" của Java cho Nhà sản xuất nhanh, Người tiêu dùng chậm

Dưới đây là một sơ đồ miêu tả một "giai đoạn" đầy đủ trong ứng dụng của chúng tôi so với một kịch bản phổ biến hơn:

 Our Application     Common Scenario 
2N +--------+--------+ 
    |PPPPPPPP|oooooooo|           P = Producer 
    |PPPPPPPP|oooooooo|           C = Consumer 
    N +--------+--------+  N +--------+--------+--------+  o = Other Work 
    |CPCPCPCP|CCCCCCCC|  |CPCPCPCP|CPCPCPCP|oooooooo|  N = number of tasks 
    |CPCPCPCP|CCCCCCCC|  |CPCPCPCP|CPCPCPCP|oooooooo| 
    -------------------  ---------------------------- 
    0  T/2  T  0  T/2  T  3T/2 

Ý tưởng là để tối đa hóa thông lượng bằng cách không ức chế các nhà sản xuất.

Dữ liệu mà tác vụ của chúng tôi hoạt động dễ dàng được tuần tự hóa, vì vậy tôi dự định triển khai giải pháp hệ thống tệp để làm đầy tất cả các tác vụ không thể ngay lập tức được thỏa mãn.

Tôi đang sử dụng Java ThreadPoolExecutor với số BlockingQueue với dung lượng tối đa để đảm bảo chúng tôi không hết bộ nhớ. Vấn đề là trong việc thực hiện một hàng đợi "tầng", nơi mà các nhiệm vụ có thể được xếp hàng trong bộ nhớ được thực hiện ngay lập tức, nếu không dữ liệu được xếp hàng đợi trên đĩa.

tôi đã đi lên với hai giải pháp khả thi:

  1. Thực hiện một BlockingQueue từ đầu, sử dụng LinkedBlockingQueue hoặc ArrayBlockingQueue thực hiện như một tài liệu tham khảo. Điều này có thể đơn giản như việc sao chép việc thực hiện trong thư viện chuẩn và thêm đọc/ghi hệ thống tập tin.
  2. Tiếp tục sử dụng triển khai BlockingQueue tiêu chuẩn, triển khai FilesystemQueue riêng biệt để lưu trữ dữ liệu của tôi và sử dụng một hoặc nhiều chủ đề để xóa các tệp, tạo Runnable s và enqueue chúng bằng cách sử dụng ThreadPoolExecutor.

Một trong hai phương pháp này có hợp lý và có khả năng tiếp cận tốt hơn không?

Trả lời

2

Các đầu tiên lựa chọntăng có sẵn đống không gian kích thước, như đề xuất bởiDimitar Dimitrov, sử dụng cờ nhớ -Xmx, ví dụ java -Xmx2048m

Từ Oracle's Documentation: Lưu ý rằng JVM sử dụng nhiều bộ nhớ hơn heap. Ví dụ: Các phương thức Java, ngăn xếp luồng và tay cầm tự nhiên được cấp phát trong bộ nhớ tách biệt khỏi heap, cũng như các cấu trúc dữ liệu nội bộ JVM.

Đây cũng là một sơ đồ về cách java bộ nhớ heaploại.

enter image description here


Các thứ hai tùy chọn là sử dụng một thư viện mà thực hiện các chức năng yêu cầu. Vì mục đích đó bạn có thể sử dụng ashes-queue

Từ cái nhìn tổng quan dự án của: Đây là một thực hiện FIFO đơn giản trong Java trong đó có hỗ trợ dai dẳng. Tức là, nếu hàng đợi đầy, tin nhắn bị tràn sẽ bị lưu lại và khi có sẵn các khe , chúng sẽ được đưa trở lại vào bộ nhớ.


Các tùy chọn thứ batạo thực hiện của riêng bạn. Đối với vấn đề đó, bạn có thể xem trước this thread hướng dẫn bạn đến mục đích đó.

Đề xuất của bạn được bao gồm trong tùy chọn thứ ba cuối cùng này. Cả hai đều hợp lý. Từ quan điểm thực hiện, bạn nên chọn tùy chọn đầu tiên vì nó sẽ đảm bảo việc triển khai và thiết kế rõ ràng dễ dàng hơn.

2

Điều này nghe giống như tình huống lý tưởng để sử dụng hàng đợi JMS, thay vì hệ thống tệp.

Thay vì sử dụng hàng đợi chặn, hãy đăng thông báo lên hàng đợi JMS liên tục. Bạn vẫn có thể thử cách tiếp cận theo từng cấp, kết hợp hàng đợi JMS song song với BlockingQueue, đăng lên hàng đợi JMS khi BlockingQueue đầy, nhưng tôi chắc chắn rằng cách tiếp cận JMS thuần túy sẽ hoạt động tốt.

4

Trước khi đi cho một giải pháp phức tạp hơn, bạn có thực sự tự tin rằng sử dụng một biên giới BlockingQueue bị ràng buộc là một đối phó-breaker cho bạn? Nó có thể bật ra rằng tăng kích thước heap của bạn và preallocating năng lực đủ rộng lượng vẫn OK cho bạn. Nó sẽ cho phép bạn tránh sự phức tạp và hiệu suất không chắc chắn, về giá của GC tạm dừng mà là tốt trong khu vực thoải mái của bạn.

Tuy nhiên, nếu khối lượng công việc của bạn không cân bằng, nó có thể tận dụng số lượng thư không phù hợp với bộ nhớ (so với hàng đợi chặn MPMC đã được chứng minh), có vẻ như bạn cần phiên bản ActiveMQ đơn giản hơn hoặc của nó Apollo off-shoot. Tùy thuộc vào ứng dụng của bạn, bạn có thể thấy các tính năng khác của ActiveMQ hữu ích, trong trường hợp đó bạn có thể sử dụng nó trực tiếp. Nếu không, bạn có thể tốt hơn khi tìm kiếm không gian JMS, vì bowmore đề xuất.

Các vấn đề liên quan