2013-02-26 43 views
9

Tôi có một vấn đề với một ứng dụng đang chạy nhiều luồng Java. Ứng dụng chạy một số chuỗi làm việc liên tục nhìn vào hàng đợi nhập liệu và nếu có thư trong hàng đợi, chúng sẽ kéo chúng ra và xử lý chúng.Đa luồng Java trong tải CPU

Trong số các chuỗi làm việc đó, có một chuỗi xác minh khác được lên lịch để thực hiện tại một khoảng thời gian cố định để kiểm tra xem máy chủ (mà ứng dụng chạy) vẫn đang ở trạng thái "tốt" để chạy ứng dụng. Chủ đề này cập nhật giá trị AtomicBoolean mà lần lượt được xác minh bởi chuỗi hoạt động trước khi chúng bắt đầu nhìn trộm để xem máy chủ có OK không.

Vấn đề của tôi là trong trường hợp tải CPU cao, luồng có trách nhiệm xác minh sẽ mất nhiều thời gian hơn vì nó phải cạnh tranh với tất cả các chủ đề khác. Nếu AtomicBoolean không được cập nhật sau một khoảng thời gian nhất định, nó sẽ tự động được đặt thành false, gây cho tôi một nút cổ chai khó chịu.

Cách tiếp cận ban đầu của tôi là tăng mức độ ưu tiên của chuỗi xác minh, nhưng tìm hiểu sâu hơn, tôi nhận thấy đây không phải là hành vi được đảm bảo và thuật toán không nên dựa vào mức độ ưu tiên của luồng để hoạt động chính xác.

Bất kỳ ai cũng có ý tưởng thay thế? Cảm ơn!

+1

Cung cấp cho chúng tôi mã số – Andremoniy

+0

Thông thường, các ưu tiên không nên ảnh hưởng đến hoạt động đúng, nhưng điều này có vẻ là một vấn đề điều chỉnh. Giả sử chuỗi xác minh là thấp trên tải CPU, và các công nhân cần nhiều CPU hơn, cung cấp cho họ ưu tiên thấp hơn. Ngoài ra, hãy đảm bảo thời gian chờ cho nguyên tử của bạn không được đặt quá thấp. –

+2

Một lần nữa: hiển thị cho chúng tôi mã nguồn của 'chuỗi xác minh' của bạn. – Andremoniy

Trả lời

0

Chủ đề khác không có nghĩa là hiệu suất tốt hơn. Thông thường nếu bạn có lõi kép, 2 luồng cho hiệu suất tốt nhất, 3 hoặc nhiều hơn bắt đầu trở nên tệ hơn. Quad core nên xử lý 4 chủ đề tốt nhất, v.v. Vì vậy, hãy cẩn thận bao nhiêu chủ đề bạn sử dụng.

Bạn có thể đặt các chủ đề khác để ngủ sau khi chúng thực hiện công việc của mình và cho phép các chủ đề khác thực hiện phần của chúng. Tôi tin rằng Thread.yield() sẽ tạm dừng thread hiện tại để cung cấp thời gian cho các luồng khác.

Nếu bạn muốn chuỗi của mình chạy liên tục, tôi khuyên bạn nên tạo hai luồng chính, chuỗi A và B. Sử dụng A cho chuỗi xác minh và từ B, tạo chủ đề khác. Do đó luồng A nhận được nhiều thời gian thực thi hơn.

+0

Tôi nghĩ rằng theo mặc định một chủ đề có được ưu tiên của các chủ đề tạo ra nó như vậy trong tình huống mà bạn mô tả các chủ đề tạo ra với chủ đề B sẽ có prio giống như chủ đề A. Đúng tôi nếu tôi sai –

+0

Có thể được, Tôi không chắc chắn, nhưng những gì tôi nói ở đây là bạn tiếp tục chuyển đổi giữa thread A và B. B sẽ cần phải chạy nhiều chủ đề, trong khi A sẽ là một chủ đề duy nhất, do đó A sẽ nhận được nhiều thời gian hơn. Theo ưu tiên, tôi không có ý định ưu tiên luồng chính xác, ý tôi là nó sẽ có nhiều thời gian thực thi hơn. Hãy để tôi sửa nó để làm cho nó rõ ràng hơn. – Steve

0

Một cách tiếp cận cũ của trường để điều chỉnh tốc độ công việc, không sử dụng chuỗi kiểm tra sức khỏe (và vì vậy, bỏ qua những vấn đề này) là chặn hoặc từ chối yêu cầu thêm vào hàng đợi nếu hàng đợi dài hơn nói 100. Điều này áp dụng áp lực trở lại năng động trên cho các khách hàng tạo ra tải, làm chậm chúng xuống khi các chủ đề công nhân quá tải.

Cách tiếp cận này đã được thêm vào thư viện Java 1.5, xem java.util.concurrent.ArrayBlockingQueue. Phương thức put (o) của nó sẽ bị chặn nếu hàng đợi đầy.

+0

Thật không may tôi không thể chạm vào hàng đợi vì chúng nằm trong phạm vi điều chỉnh –

0

Bạn có sử dụng khung công tác Executor (từ gói đồng thời của Java) không? Nếu không cho nó một shot. Bạn có thể thử sử dụng ScheduledExecutorService cho chuỗi xác minh.

+0

Tôi thực sự đang sử dụng ScheduledThreadPoolExecutor cho chuỗi xác thực. Các chủ đề khác cũng được tạo với ScheduledThreadPoolExecutor nhưng trong một nhóm khác. Công việc mà các luồng này thực hiện có một vòng lặp while để chúng thực thi liên tục. Có lẽ tôi đang thiếu một cái gì đó. –

1

Thay vì nhìn trộm vào một cấu trúc dữ liệu hàng đợi thường xuyên, sử dụng LinkedBlockingQueue gói java.util.concurrent của.

Những gì bạn có thể làm là chạy một nhóm chủ đề (bạn có thể sử dụng hồ bơi cố định của dịch vụ thực thi, nghĩa là một số công nhân bạn chọn) và làm LinkedBlockingQueue.take().

Nếu thư đến hàng đợi, nó được nạp vào một trong các chuỗi chờ (vâng, hãy chặn luồng cho đến khi có thứ gì đó được nạp cùng).

Java API Reference for Linked Blocking Queue's take method

HTH.

+0

Đã chọn. Không chỉ quay & liếc trong chủ đề công nhân của bạn, yêu cầu họ chờ() trên một khóa hoặc chặn trên hàng đợi khi không có gì để làm. Nhiều khả năng đó là chủ đề công nhân quá tích cực của bạn đang giết chết phản ứng. Làm điều đó đúng. –