Đầu tiên, một chuỗi Java (hoặc .NET)! = Một chuỗi hạt nhân/hệ điều hành.
Một Java Thread là trình bao bọc cấp cao tóm tắt một số chức năng của chuỗi hệ thống; các loại chủ đề này còn được gọi là chủ đề được quản lý. Ở cấp độ hạt nhân, một luồng chỉ có 2 trạng thái, đang chạy và không chạy. Có một số thông tin quản lý (ngăn xếp, con trỏ hướng dẫn, id chủ đề, vv) mà hạt nhân theo dõi, nhưng không có điều như vậy ở cấp hạt nhân như là một chủ đề trong trạng thái TIMED_WAITING
(tương đương .NET với WaitSleepJoin
tiểu bang). Những "tiểu bang" chỉ tồn tại trong các bối cảnh đó (một phần lý do tại sao C++ std::thread
không có thành viên state
).
Có nói rằng, khi một chuỗi được quản lý đang bị chặn, nó đang được thực hiện như vậy trong một vài cách (tùy thuộc vào cách nó đang được yêu cầu bị chặn ở cấp quản lý); các triển khai mà tôi đã thấy trong OpenJDK cho mã luồng sử dụng các semaphores để xử lý các chờ đợi được quản lý (đó là những gì tôi đã thấy trong các khung công tác C++ khác có một loại luồng "được quản lý" cũng như trong .NET Core và sử dụng mutex cho các loại waits/locks khác.
Vì hầu hết các triển khai sẽ sử dụng một số loại cơ chế khóa (như semaphore hoặc mutex), hạt nhân thường làm điều tương tự (ít nhất là câu hỏi của bạn có liên quan); có nghĩa là, hạt nhân sẽ lấy sợi ra khỏi hàng đợi "chạy" và đặt nó vào hàng đợi "chờ" (một context switch).Bắt đầu lập lịch trình và đặc biệt cách nhân xử lý việc thực thi các luồng nằm ngoài phạm vi của Q & A này, đặc biệt là vì bạn đang đặt câu hỏi liên quan đến Java và Java có thể chạy trên một vài kiểu hệ điều hành khác nhau (mỗi xử lý luồng hoàn toàn khác nhau).
Trả lời câu hỏi của bạn trực tiếp hơn:
Có một số lượng lớn các chủ đề trong JVM tiêu thụ nhiều tài nguyên (bộ nhớ, CPU), khi đề là TIMED_WAIT nhà nước (không ngủ)> 99,9% thời gian ?
Để làm điều này, có một vài điều cần lưu ý: chuỗi được tạo sẽ tiêu thụ bộ nhớ cho JVM (ngăn xếp, ID, bộ thu gom rác, v.v.) và hạt nhân tiêu thụ bộ nhớ hạt nhân để quản lý luồng tại hạt nhân cấp độ. Bộ nhớ đó được tiêu thụ không thay đổi trừ khi bạn nói cụ thể như vậy. Vì vậy, nếu thread đang ngủ hoặc chạy, bộ nhớ là như nhau.
CPU là điều sẽ thay đổi dựa trên hoạt động của chuỗi và số lượng chuỗi được yêu cầu (nhớ, luồng cũng tiêu thụ tài nguyên hạt nhân, do đó phải được quản lý ở cấp hạt nhân, do đó, nhiều chuỗi phải được xử lý , thời gian hạt nhân phải được tiêu thụ để quản lý chúng).
Hãy nhớ rằng thời gian hạt nhân lên lịch và chạy chủ đề cực kỳ nhỏ (đó là một phần của điểm thiết kế), nhưng nó vẫn là điều cần xem xét nếu bạn có kế hoạch chạy lô của chủ đề; Ngoài ra, nếu bạn biết ứng dụng của bạn sẽ chạy trên một CPU (hoặc cụm) chỉ với một vài lõi, bạn càng có ít lõi hơn, thì hạt nhân càng phải chuyển ngữ cảnh, thêm thời gian bổ sung nói chung.
Khi chuỗi đang chờ, chi phí cho CPU là bao nhiêu để duy trì chúng nếu cần thiết?
Không có. Xem ở trên, nhưng chi phí CPU được sử dụng để quản lý các chủ đề không thay đổi dựa trên bối cảnh luồng. CPU bổ sung có thể được sử dụng để chuyển đổi ngữ cảnh và chắc chắn CPU phụ sẽ được sử dụng bởi chính các chủ đề khi hoạt động, nhưng không có thêm "chi phí" cho CPU để duy trì một chuỗi chờ đợi so với chuỗi đang chạy.
Câu trả lời cũng áp dụng cho môi trường không liên quan đến JVM (như hạt nhân Linux)?
Có và không. Như đã nói, các bối cảnh được quản lý thường áp dụng cho hầu hết các loại môi trường đó (ví dụ: Java, .NET, PHP, Lua, v.v.), nhưng các bối cảnh đó có thể khác nhau và thành ngữ luồng và chức năng chung phụ thuộc vào hạt nhân đang được sử dụng. Vì vậy, trong khi một hạt nhân cụ thể có thể xử lý 1000+ chủ đề cho mỗi quá trình, một số có thể có giới hạn cứng, những người khác có thể có các vấn đề khác với số lượng chuỗi cao hơn cho mỗi quá trình; bạn sẽ phải tham khảo thông số kỹ thuật OS/CPU để xem loại giới hạn nào bạn có thể có.
Vì hầu hết các chủ đề sẽ được ở trạng thái TIMED_WAIT (Java của Timer() gọi các Object.wait (phương pháp dài)) đại đa số các vòng đời của chúng, nó vẫn ảnh hưởng đến CPU trong một cách rất lớn ?
Không (một phần của điểm của chủ đề bị chặn), nhưng cần lưu ý: nếu (cạnh trường hợp) tất cả (hoặc> 50%) của các chuỗi đó cần chạy cùng một lúc?Nếu bạn chỉ có một vài chủ đề quản lý các gói của bạn, điều đó có thể không phải là một vấn đề, nhưng nói rằng bạn có 500+; 250 chủ đề tất cả được đánh thức cùng một lúc sẽ gây ra tranh chấp CPU lớn.
Vì bạn chưa đăng bất kỳ mã nào, thật khó để đưa ra đề xuất cụ thể cho kịch bản của bạn, nhưng sẽ có khuynh hướng lưu cấu trúc thuộc tính dưới dạng lớp và giữ lớp đó trong danh sách hoặc bản đồ băm có thể được tham chiếu trong một Timer
(hoặc một chuỗi riêng biệt) để xem thời gian hiện tại có khớp với thời gian hết hạn của gói hay không, sau đó mã "hết hạn" sẽ chạy. Điều này giảm số lượng các chủ đề xuống còn 1 và thời gian truy cập là O(1)
; nhưng một lần nữa, không có mã, gợi ý đó có thể không hoạt động trong kịch bản của bạn.
Hy vọng điều đó sẽ hữu ích.
Có bao nhiêu chủ đề bạn đang nghĩ có thể đang đợi? Một vài trăm hoặc hơn có thể không phải là thuế trên hạt nhân để kiểm tra các chủ đề và khi họ cần phải được lên kế hoạch, nhưng nếu bạn đang xếp hàng lên 500 +, bạn có thể muốn xem xét lại cách tiếp cận của bạn .. – txtechhelp
có hơn một vài trăm. Bạn có thể giải thích tại sao hạt nhân phải liên tục kiểm tra các luồng trên 'TIMED_WAIT'? Tôi đã cố gắng tìm thông tin về cách hạt nhân thực hiện điều này một cách cụ thể nhưng không thể tìm thấy bất kỳ thông tin mong muốn nào. – PhotometricStereo
ScheduledExecutor/hàng đợi ưu tiên theo dấu thời gian hết hạn với một chuỗi đơn. – zapl