Chủ đề hay ThreadPool? Đã sửa lỗi hay Dynamic ThreadPool?


8

Tôi có một chương trình java nghe trên một cổng cho đầu vào. Dựa trên Input, nó gọi một dịch vụ web và sau đó trả lại thành công / thất bại cho chương trình máy khách.

Tôi rẽ nhánh một chủ đề cho mỗi kết nối khách hàng. Phản hồi lại cho máy khách kết nối với chương trình phải nhanh chóng.

Đây là những lựa chọn tôi đang xem xét

  1. sử dụng chủ đề thường xuyên
  2. sử dụng ExecutorServicevớinewFixedThreadPool
  3. sử dụng ExecutorServicevớinewCachedThreadPool

Lý do tôi đang xem xét Pools là vì các chủ đề của tôi bị rút ngắn - họ chỉ cần gọi một dịch vụ web, trả lại kết quả cho khách hàng và đóng kết nối.

Tôi không nghĩ newFixedThreadPoolsẽ là điều đúng đắn vì sau đó các kết nối sẽ đợi trong hàng đợi để nhận một chuỗi.

newCachedThreadPoolsẽ là hoàn hảo ngoại trừ một điều - chủ đề chết sau một phút. Trong trường hợp của tôi, tôi nhận được một loạt các kết nối - tức là nhiều kết nối và sau đó có thể có một thời gian tạm lắng trong vài phút và sau đó lại bùng nổ. Tôi nghĩ rằng các chủ đề trong CacheedThreadPool sẽ chết và một lần nữa sẽ phải được tạo lại - vì vậy trong trường hợp này, đôi khi nó có thể hoạt động như # 1.

Lý tưởng nhất là tôi rất thích có newCachedThreadPooltối thiểu - tức là một cài đặt cho biết số lượng chủ đề sẽ không bao giờ xuống dưới mức 20. Vì vậy, các chủ đề nhàn rỗi bị giết nhưng không bao giờ cho phép đi dưới ngưỡng tối thiểu.

Có bất cứ điều gì như thế này có sẵn? Hoặc có bất kỳ lựa chọn thay thế tốt hơn?


Hãy xem QuickServer.org thay vì máy chủ socket riêng. Nó làm những gì bạn muốn -> ổ cắm và chủ đề và có nhiều mẫu. có thể làm cho nó chạy trong 30 phút. Đã thử nghiệm và ổn định, đã sử dụng nó trong 3 dự án. "Thư viện / khung công tác Java mã nguồn mở để tạo nhanh các ứng dụng máy chủ TCP đa máy khách mạnh mẽ"
tgkprog

Câu trả lời:


8

Các phương thức trong lớp Executors chỉ là các phương thức tiện lợi cho các trường hợp sử dụng phổ biến. Có rất nhiều tùy chọn có sẵn để tạo nhóm luồng.

Để tạo điều tương tự như Executors.newCachedThreadPool () nhưng với tối thiểu 20 luồng (điều này được sao chép từ phương thức trong Executors, với kích thước luồng lõi thay đổi từ 0 đến 20).

        return new ThreadPoolExecutor(20, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());

4

Câu hỏi thú vị.

Tôi muốn giới thiệu chống lại newCachedThreadPool. Nó sẽ sinh ra nhiều chủ đề khi cần thiết mà không có giới hạn trên. Điều đó thật tồi tệ!

Cách tiếp cận được đề xuất bởi Michael có vẻ tốt. Sử dụng ThreadPoolExecutorvà sử dụng một số bạn cảm thấy thoải mái với kích thước nhóm lõi. Đặt số lượng chủ đề tối đa thành một cái gì đó bạn muốn dung thứ (hoặc máy chủ của bạn có thể xử lý).

Xin lưu ý rằng bạn không thể làm được gì nhiều khi bạn sử dụng hết tài nguyên (Hàng đợi đã đầy và số lượng luồng tối đa đang hoạt động). Trong trường hợp đó, bạn có thể thực hiện một trong hai điều sau: bỏ kết nối mới hoặc áp dụng áp lực ngược (không chấp nhận công việc mới bằng cách chặn). TPE theo mặc định ném RejectedExecutionExceptionkhi nó đầy, nhưng thật dễ dàng để thực hiện hành vi Chặn. Trong thực tế, đây là một triển khai mã nguồn mở của BlockingThreadPoolExecutor .



0

Tôi nghĩ rằng sử dụng một trình bao bọc trên ThreadPoolExecutor là một cách tốt để đi. Trình bao bọc để bạn có thể hiển thị một số khởi tạo (như tên nhóm, số luồng, v.v.) và phương thức để thêm tác vụ (Runnable) vào nhóm được tạo trước đó bằng một trong các phương thức init của bạn.

Trình bao bọc có thể thay đổi nhóm mà nó sử dụng mà không ảnh hưởng đến mã khác, cộng với có thể hiển thị các phương thức khác như số lượng luồng, kiểm toán (trước / sau tác vụ) theo cách nhất quán

Bạn cũng có thể triển khai nhà máy Thread của riêng mình cho nhóm của bạn, có thể có tên tùy chỉnh, mức độ ưu tiên và ít nhất là móc vào UncaughtExceptionHandler để bạn có thể ghi lại bất kỳ lỗi nào.

trong trình bao bọc hồ bơi của tôi, chúng ta có các phương thức như

public static boolean queqeAdd(String poolName, int coreSize, int maxSize, boolean usePriorityQ, String threadNamePrefix, int timeOutSeconds) {...}
public static void execute(String poolName, Runnable command, Integer priority){...}
public static long tasksCount(String poolName) 
public static long tasksCompletedCount(String poolName) 
public static int clearPoolRequest(String poolName, boolean intrpt) 
public static int shutdownPoolRequest(String poolName) 
public static void executeAll(String poolName, List<Runnable> lst) 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.