Java VM có thể hỗ trợ bao nhiêu luồng? Điều này thay đổi theo nhà cung cấp? bởi hệ điều hành? những yếu tố khác?
Java VM có thể hỗ trợ bao nhiêu luồng? Điều này thay đổi theo nhà cung cấp? bởi hệ điều hành? những yếu tố khác?
Câu trả lời:
Điều này phụ thuộc vào CPU bạn đang sử dụng, trên HĐH, vào các quy trình khác đang làm gì, trên bản phát hành Java nào bạn đang sử dụng và các yếu tố khác. Tôi đã thấy một máy chủ Windows có> 6500 Chủ đề trước khi đưa máy xuống. Tất cả các chủ đề đã không làm bất cứ điều gì, tất nhiên. Khi máy đạt khoảng 6500 Chủ đề (bằng Java), toàn bộ máy bắt đầu gặp sự cố và không ổn định.
Kinh nghiệm của tôi cho thấy Java (các phiên bản gần đây) có thể vui vẻ tiêu thụ nhiều Chủ đề như chính máy tính có thể lưu trữ mà không gặp sự cố.
Tất nhiên, bạn phải có đủ RAM và bạn phải khởi động Java với đủ bộ nhớ để làm mọi thứ mà Chủ đề đang làm và có một ngăn xếp cho mỗi Chủ đề. Bất kỳ máy nào có CPU hiện đại (vài thế hệ AMD hoặc Intel gần đây nhất) và có bộ nhớ 1 - 2 Gig (tùy thuộc vào hệ điều hành) có thể dễ dàng hỗ trợ JVM với hàng ngàn Chủ đề.
Nếu bạn cần một câu trả lời cụ thể hơn câu này, cách tốt nhất của bạn là hồ sơ.
Ừm, rất nhiều.
Có một vài thông số ở đây. VM cụ thể, cộng với thường có các tham số thời gian chạy trên VM. Điều đó phần nào được điều khiển bởi hệ điều hành: HĐH cơ bản có hỗ trợ gì cho các luồng và nó có những hạn chế gì đối với chúng? Nếu VM thực sự sử dụng các luồng cấp độ hệ điều hành, thì luồng xử lý màu đỏ / luồng xanh cũ tốt.
"Hỗ trợ" nghĩa là gì một câu hỏi khác. Nếu bạn viết một chương trình Java giống như
class DieLikeADog {
public static void main(String[] argv){
for(;;){
new Thread(new SomeRunaable).start();
}
}
}
(và đừng phàn nàn về các chi tiết cú pháp nhỏ, tôi đang uống tách cà phê đầu tiên của mình), sau đó bạn chắc chắn sẽ mong đợi có được hàng trăm hoặc hàng ngàn chuỗi hoạt động. Nhưng việc tạo một Chủ đề tương đối tốn kém và chi phí lập lịch có thể trở nên khó khăn; không rõ ràng rằng bạn có thể có những chủ đề đó làm bất cứ điều gì hữu ích.
Được rồi, không thể cưỡng lại. Đây là chương trình thử nghiệm nhỏ của tôi, với một vài chỉnh sửa:
public class DieLikeADog {
private static Object s = new Object();
private static int count = 0;
public static void main(String[] argv){
for(;;){
new Thread(new Runnable(){
public void run(){
synchronized(s){
count += 1;
System.err.println("New thread #"+count);
}
for(;;){
try {
Thread.sleep(1000);
} catch (Exception e){
System.err.println(e);
}
}
}
}).start();
}
}
}
Trên OS / X 10.5.6 trên Intel và Java 6 5 (xem bình luận), đây là những gì tôi nhận được
Chủ đề mới # 2547 Chủ đề mới # 2548 Chủ đề mới # 2549 Không thể tạo chủ đề: 5 Chủ đề mới # 2550 Ngoại lệ trong luồng "chính" java.lang.OutOfMemoryError: không thể tạo luồng gốc mới tại java.lang.Thread.start0 (Phương thức gốc) tại java.lang.Thread.start (Thread.java giáp92) tại DieLikeADog.main (DieLikeADog.java:6)
Sau khi đọc bài đăng của Charlie Martin, tôi tò mò về việc liệu kích thước heap có làm thay đổi số lượng chủ đề bạn có thể tạo hay không và tôi hoàn toàn chết lặng trước kết quả.
Sử dụng JDK 1.6.0_11 trên Vista Home Premium SP1, tôi đã thực thi ứng dụng thử nghiệm của Charlie với các kích cỡ heap khác nhau, từ 2 MB đến 1024 MB.
Ví dụ, để tạo một đống 2 MB, tôi sẽ gọi JVM bằng các đối số -Xms2m -Xmx2m.
Đây là kết quả của tôi:
2 mb --> 5744 threads
4 mb --> 5743 threads
8 mb --> 5735 threads
12 mb --> 5724 threads
16 mb --> 5712 threads
24 mb --> 5687 threads
32 mb --> 5662 threads
48 mb --> 5610 threads
64 mb --> 5561 threads
96 mb --> 5457 threads
128 mb --> 5357 threads
192 mb --> 5190 threads
256 mb --> 5014 threads
384 mb --> 4606 threads
512 mb --> 4202 threads
768 mb --> 3388 threads
1024 mb --> 2583 threads
Vì vậy, yeah, kích thước heap chắc chắn có vấn đề. Nhưng mối quan hệ giữa kích thước heap và số lượng luồng tối đa là tỷ lệ thuận.
Thật là kỳ lạ.
Tôi biết câu hỏi này khá cũ nhưng chỉ muốn chia sẻ những phát hiện của tôi.
Máy tính xách tay của tôi có thể xử lý chương trình sinh ra các 25,000
luồng và tất cả các luồng đó ghi một số dữ liệu trong cơ sở dữ liệu MySql trong khoảng thời gian thông thường là 2 giây.
Tôi chạy chương trình này với 10,000 threads
cho 30 minutes continuously
thì cũng hệ thống của tôi đã ổn định và tôi đã có thể làm hoạt động bình thường khác như duyệt web, mở, đóng các chương trình khác, vv
Với 25,000 threads
hệ thống slows down
nhưng nó vẫn đáp ứng.
Với 50,000 threads
hệ thống stopped responding
ngay lập tức và tôi phải khởi động lại hệ thống của mình một cách thủ công.
Chi tiết hệ thống của tôi như sau:
Processor : Intel core 2 duo 2.13 GHz
RAM : 4GB
OS : Windows 7 Home Premium
JDK Version : 1.6
Trước khi chạy tôi đặt đối số jvm -Xmx2048m
.
Hy vọng nó giúp.
Các lý thuyết tối đa tuyệt đối thường là một quá trình không gian địa chỉ dùng chia cho thread stack kích thước (mặc dù trong thực tế, nếu tất cả các bộ nhớ của bạn được dành riêng cho ngăn xếp chủ đề, bạn sẽ không có một chương trình làm việc ...).
Vì vậy, trong Windows 32 bit, ví dụ, trong đó mỗi quy trình có không gian địa chỉ người dùng là 2GB, cung cấp cho mỗi luồng có kích thước ngăn xếp 128K, bạn sẽ mong đợi tối đa tuyệt đối là 16384 luồng (= 2 * 1024 * 1024/128). Trong thực tế, tôi thấy tôi có thể bắt đầu khoảng 13.000 dưới XP.
Sau đó, tôi nghĩ rằng về cơ bản, bạn có thể quản lý việc tung hứng nhiều luồng trong mã của mình và không thực hiện những điều ngớ ngẩn rõ ràng (chẳng hạn như làm cho tất cả chúng chờ đợi trên cùng một đối tượng sau đó gọi notifyAll () ...), và (b) liệu hệ điều hành có thể. Về nguyên tắc, câu trả lời cho (b) là "có" nếu câu trả lời cho (a) cũng là "có".
Ngẫu nhiên, bạn có thể chỉ định kích thước ngăn xếp trong hàm tạo của Thread ; bạn không cần (và có lẽ không nên) lộn xộn với các tham số VM cho việc này.
Tôi nhớ lại đã nghe một cuộc nói chuyện của Clojure khi anh ta phải chạy một trong những ứng dụng của mình trên một số máy chuyên dụng tại một triển lãm thương mại với hàng ngàn lõi (9000?), Và nó đã tải tất cả chúng. Thật không may, tôi không thể tìm thấy liên kết ngay bây giờ (trợ giúp?).
Dựa vào đó, tôi nghĩ an toàn khi nói rằng phần cứng và mã của bạn là các yếu tố giới hạn, không phải là JVM.
Sau khi chơi xung quanh với lớp DieLikeACode của Charlie, có vẻ như kích thước ngăn xếp luồng Java là một phần rất lớn trong số lượng luồng bạn có thể tạo.
-Xss đặt kích thước ngăn xếp luồng java
Ví dụ
java -Xss100k DieLikeADog
Nhưng, Java có giao diện Executor . Tôi sẽ sử dụng điều đó, bạn sẽ có thể gửi hàng ngàn tác vụ Runnable và để Executor xử lý các tác vụ đó với một số luồng cố định.
Runnable
/ Callable
thực sự cần phải chạy liên tục, như khi nó phải xử lý giao tiếp. Nhưng nó hoàn hảo cho các truy vấn SQL.
Ít nhất trên Mac OS X 10.6 32bit, có giới hạn (2560) bởi hệ điều hành. Kiểm tra luồng stackoverflow này .
Thông tin bổ sung cho các hệ thống linux (systemd) hiện đại.
Có nhiều tài nguyên về giá trị này có thể cần điều chỉnh (chẳng hạn như Cách tăng số lượng luồng JVM tối đa (Linux 64 bit) ); tuy nhiên, một giới hạn mới được áp đặt theo cách giới hạn "T taskMax" của systemd, thiết lập pids.max trên cgroup.
Đối với phiên đăng nhập của UserTasksMax mặc định là 33% pids_max hạn hạt nhân (thường là 12.288) và có thể được ghi đè trong /etc/systemd/logind.conf.
Đối với các dịch vụ, DefaultT taskMax mặc định là 15% giới hạn kernel pids_max (thường là 4.915). Bạn có thể ghi đè lên dịch vụ bằng cách đặt T taskMax trong "chỉnh sửa systemctl" hoặc cập nhật DefaultT taskMax trong /etc/systemd/system.conf
Bạn có thể xử lý bất kỳ số lượng chủ đề; không có giới hạn. Tôi đã chạy đoạn mã sau trong khi xem phim và sử dụng NetBeans, và nó hoạt động bình thường / không bị tạm dừng máy. Tôi nghĩ rằng bạn có thể giữ nhiều chủ đề hơn chương trình này.
class A extends Thread {
public void run() {
System.out.println("**************started***************");
for(double i = 0.0; i < 500000000000000000.0; i++) {
System.gc();
System.out.println(Thread.currentThread().getName());
}
System.out.println("************************finished********************************");
}
}
public class Manager {
public static void main(String[] args) {
for(double j = 0.0; j < 50000000000.0; j++) {
A a = new A();
a.start();
}
}
}
main
sẽ ném OutOfMemoryError
vào máy của tôi, nói rằng nó không thể tạo thêm bất kỳ chủ đề nào. Có lẽ @AnilPal, bạn đã không nhận thấy điều đó. Tôi đề nghị bao gồm một câu lệnh in khác trong main(..)
phương thức, để thấy rõ khi nào nó ngừng tạo chủ đề mới sau khi ném lỗi.