Java VM สามารถรองรับเธรดได้กี่เธรด


212

Java VM สามารถรองรับเธรดได้กี่เธรด สิ่งนี้แตกต่างกันไปตามผู้ขายหรือไม่ โดยระบบปฏิบัติการ? ปัจจัยอื่น ๆ ?

คำตอบ:


170

ขึ้นอยู่กับซีพียูที่คุณใช้บนระบบปฏิบัติการกระบวนการอื่นกำลังทำอะไรจาวาปล่อยสิ่งที่คุณใช้และปัจจัยอื่น ๆ ฉันเคยเห็นเซิร์ฟเวอร์ Windows มี> 6500 เธรดก่อนนำเครื่องลงมา แน่นอนว่าเธรดส่วนใหญ่ไม่ได้ทำอะไรเลย เมื่อเครื่องมีจำนวนประมาณ 6500 เธรด (ใน Java) เครื่องทั้งหมดก็เริ่มมีปัญหาและไม่เสถียร

ประสบการณ์ของฉันแสดงให้เห็นว่า Java (เวอร์ชันล่าสุด) สามารถใช้เธรดได้อย่างมีความสุขเท่าที่คอมพิวเตอร์สามารถโฮสต์ได้โดยไม่มีปัญหา

แน่นอนคุณต้องมี RAM เพียงพอและคุณต้องเริ่มต้น Java ด้วยหน่วยความจำเพียงพอที่จะทำทุกอย่างที่เธรดกำลังทำอยู่และมีสแต็กสำหรับแต่ละเธรด เครื่องใด ๆ ที่มี CPU ที่ทันสมัย ​​(รุ่นล่าสุดของ AMD หรือ Intel) และหน่วยความจำ 1-2 กิกะไบต์ (ขึ้นอยู่กับระบบปฏิบัติการ) สามารถรองรับ JVM ด้วยเธรดนับพัน

หากคุณต้องการคำตอบที่เฉพาะเจาะจงมากกว่านี้ทางออกที่ดีที่สุดของคุณคือทำโปรไฟล์


86

อืม

มีพารามิเตอร์หลายอย่างที่นี่ VM ที่เฉพาะเจาะจงรวมถึงมักจะมีพารามิเตอร์เวลาทำงานบน VM เช่นกัน มันค่อนข้างขับเคลื่อนด้วยระบบปฏิบัติการ: ระบบปฏิบัติการที่รองรับรองรับเธรดและมีข้อ จำกัด อะไรบ้าง หาก VM ใช้เธรดระดับ OS จริง ๆ สิ่งที่ดีคือเธรดเธรดเก่า / สีเขียว

"สนับสนุน" หมายถึงคำถามอื่น หากคุณเขียนโปรแกรม Java ที่มีลักษณะเหมือน

   class DieLikeADog {
         public static void main(String[] argv){
             for(;;){
                new Thread(new SomeRunaable).start();
             }
         }
    }

(และอย่าบ่นเกี่ยวกับรายละเอียดเล็ก ๆ น้อย ๆ เกี่ยวกับไวยากรณ์ฉันอยู่ในกาแฟถ้วยแรก) จากนั้นคุณควรคาดหวังว่าจะได้รับกระทู้นับร้อยหรือหลายพันรายการ แต่การสร้างเธรดนั้นมีราคาค่อนข้างแพง ไม่ชัดเจนว่าคุณสามารถให้เธรดเหล่านั้นทำอะไรที่มีประโยชน์ได้

ปรับปรุง

โอเคไม่สามารถต้านทานได้ นี่คือโปรแกรมทดสอบเล็ก ๆ ของฉันพร้อมการปรุงแต่งสองครั้ง:

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();
        }
    }
}

บน OS / X 10.5.6 บน Intel และ Java 6 5 (ดูความคิดเห็น) นี่คือสิ่งที่ฉันได้รับ

กระทู้ใหม่ # 2547
กระทู้ใหม่ # 2548
กระทู้ใหม่ # 2549
ไม่สามารถสร้างเธรด: 5
กระทู้ใหม่ # 2550
ข้อยกเว้นในเธรด "main" java.lang.OutOfMemoryError: ไม่สามารถสร้างเธรดดั้งเดิมใหม่
        ที่ java.lang.Thread.start0 (วิธีเนทีฟ)
        ที่ java.lang.Thread.start (Thread.java,592)
        ที่ DieLikeADog.main (DieLikeADog.java:6)

10
คุณเริ่มต้น JVM ด้วยหน่วยความจำเท่าใด ที่สำคัญ.
Eddie

10
Java 6 อัพเดต 13, Ubuntu 8.10 32 บิต, 4Gig ram, การตั้งค่า JVM เริ่มต้น = 6318 เธรด
Steve K

9
เฮ้เล่นกับขนาดสแต็คเธรด java -Xss100k อนุญาตให้ฉันสร้าง 19702 เธรดใน Linux
Steve K

21
java -Xss50k ทำให้ฉันมีหัวข้อประมาณ 32k ที่ maxxed out 4gigs ram ของฉันแม้ว่า ฉันต้องหยุดกระบวนการทำงานบางอย่างเพื่อให้ได้หน่วยความจำเพียงพอบนเครื่องเพื่อแยกกระบวนการใหม่เพื่อฆ่า java;) - ช่วงเวลาที่ดี
Steve K

21
ใช้ Java 7 บน windows 7 ฉันเพิ่งสร้าง 200,000 เธรดก่อนที่ระบบของฉันจะตาย Tasks Manager แสดงกระบวนการโดยใช้ RAM 8GB ไม่แน่ใจว่าทำไมมันถึงหยุดอยู่ตรงนั้นแม้ว่า ... ฉันมี RAM 12GB ในคอมพิวเตอร์ของฉัน ดังนั้นนี่อาจกระทบขีด จำกัด อื่น ๆ
Dobes Vandermeer

50

หลังจากอ่านโพสต์ของ Charlie Martin ฉันอยากรู้ว่าขนาดฮีปสร้างความแตกต่างในจำนวนเธรดที่คุณสามารถสร้างได้หรือไม่และฉันก็รู้สึกตะลึงกับผลลัพธ์

ใช้ JDK 1.6.0_11 บน Vista Home Premium SP1 ฉันใช้งานแอปพลิเคชันทดสอบของ Charlie ที่มีขนาดฮีปต่างกันระหว่าง 2 MB ถึง 1024 MB

ตัวอย่างเช่นในการสร้างฮีป 2 MB ฉันจะเรียกใช้ JVM ด้วยอาร์กิวเมนต์ -Xms2m -Xmx2m

นี่คือผลลัพธ์ของฉัน:

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

ดังนั้นขนาดฮีปจึงมีความสำคัญอย่างแน่นอน แต่ความสัมพันธ์ระหว่างขนาดฮีปกับจำนวนเธรดสูงสุดนับเป็นสัดส่วนแบบไม่ต่อเนื่อง

ซึ่งแปลก


11
จะสมเหตุสมผลถ้าเธรดแต่ละรายการมีขนาดเท่ากัน
Thorbjørn Ravn Andersen

1
Caveat: เครื่องของฉันไม่มี RAM 2583 GB หรือสลับ และ JVM ไม่ได้จัดสรรพื้นที่ฮีปเธรดโลคัล ดังนั้นที่ไม่สามารถไม่ว่าจะเป็น ...
benjismith

49
ขนาดฮีปลดพื้นที่ที่อยู่สำหรับสแต็ก พื้นที่ที่อยู่ 256K / stack เหมาะสม
Tom Hawtin - tackline

1
ใช่นี่แสดงสิ่งเดียวกันpequenoperro.blogspot.com/2009/02/less-is-more.html
Toby

39

ฉันรู้ว่าคำถามนี้ค่อนข้างเก่า แต่ต้องการแบ่งปันสิ่งที่ค้นพบของฉัน

แล็ปท็อปของฉันสามารถจัดการโปรแกรมที่วาง25,000เธรดและเธรดเหล่านั้นทั้งหมดเขียนข้อมูลบางอย่างในฐานข้อมูล MySql ในช่วงเวลาปกติ 2 วินาที

ฉันวิ่งโปรแกรมนี้ด้วย10,000 threadsสำหรับ30 minutes continuouslyแล้วยังระบบของฉันมีเสถียรภาพและฉันก็สามารถที่จะทำดำเนินการอื่น ๆ ตามปกติเช่นการเรียกดูเปิดปิดโปรแกรมอื่น ๆ ฯลฯ

ด้วย25,000 threadsระบบslows downแต่ก็ยังตอบสนองได้

ด้วย50,000 threadsระบบstopped respondingทันทีและฉันต้องรีสตาร์ทระบบด้วยตนเอง

รายละเอียดระบบของฉันมีดังนี้:

Processor : Intel core 2 duo 2.13 GHz
RAM : 4GB
OS : Windows 7 Home Premium
JDK Version : 1.6

-Xmx2048mก่อนที่จะใช้ผมตั้งอาร์กิวเมนต์ JVM

หวังว่ามันจะช่วย


2
เสียง "ช้าลง" เช่นการสลับ
Thorbjørn Ravn Andersen

ขอบคุณ มันเป็นเครื่องจักรที่ค่อนข้างแข็งและทำงานได้ดีเกือบ 8 ปีจนกระทั่งทันใดนั้นมันก็หยุดบูทขึ้น ฉันเพียงแค่ติดตั้ง Ubuntu บนมันแทน Windows และมันเริ่มกระทืบตัวเลขอีกครั้ง :)
Shekhar

ผัด core 2 duo พร้อมเครื่องปรุงอูบุนตู: D
Pasupathi Rajamanickam

31

สูงสุดทางทฤษฎีที่แน่นอนโดยทั่วไปกระบวนการของพื้นที่ที่อยู่ของผู้ใช้แบ่งออกตามขนาดด้ายสแต็ค (แม้ว่าในความเป็นจริงหากทุกหน่วยความจำของคุณจะถูกสงวนไว้สำหรับกองด้ายคุณจะไม่ได้มีโปรแกรมการทำงาน ... )

ตัวอย่างเช่นภายใต้ Windows แบบ 32 บิตที่แต่ละกระบวนการมีพื้นที่ที่อยู่ผู้ใช้ 2GB ทำให้แต่ละเธรดมีขนาดสแต็กขนาด 128K แต่ละเธรดคุณคาดหวังจำนวนสูงสุด 16384 เธรด (= 2 * 1024 * 1024/128) ในทางปฏิบัติฉันพบว่าฉันสามารถเริ่มต้นประมาณ 13,000 ภายใต้ XP

จากนั้นฉันคิดว่าคุณจำเป็นต้องรู้หรือไม่ว่า (a) คุณสามารถจัดการการเล่นกลที่หลายเธรดในรหัสของคุณและไม่ทำสิ่งที่โง่เขลาอย่างเห็นได้ชัด (เช่นทำให้พวกเขาทั้งหมดรอวัตถุเดียวกันแล้วโทรแจ้งAllAll) และ (b) ระบบปฏิบัติการสามารถทำได้หรือไม่ โดยหลักการแล้วคำตอบสำหรับ (b) คือ "ใช่" ถ้าคำตอบของ (a) ก็คือ "ใช่" เช่นกัน

อนึ่งคุณสามารถระบุขนาดสแต็คในตัวสร้างของด้าย ; คุณไม่จำเป็นต้อง (และอาจไม่ควร) ยุ่งเกี่ยวกับพารามิเตอร์ VM สำหรับสิ่งนี้


1
ดังนั้นให้ใช้ระบบปฏิบัติการ 64 บิต เราทุกคนใช้โปรเซสเซอร์ 64 บิตมานานแค่ไหนแล้ว?
Tom Hawtin - tackline

แน่นอนว่าฉันแค่ยกตัวอย่างของขีด จำกัด เชิงทฤษฎีและเชิงปฏิบัติ ใจคุณมีมากอันยิ่งใหญ่ของเครื่อง 32 บิต (รวมถึงเซิร์ฟเวอร์) ยังคงมีออก ...
นีลเบนจามิน

2

ฉันจำได้ว่าได้ยินการพูดคุยของ Clojure ว่าเขาต้องใช้แอพใดแอพหนึ่งของเขาบนเครื่องพิเศษบางอย่างในงานแสดงสินค้าที่มีคอร์นับพัน (9000?) และมันโหลดมันทั้งหมด ขออภัยฉันไม่สามารถหาลิงก์ได้ในขณะนี้ (ช่วยด้วย)

ตามที่ฉันคิดว่ามันปลอดภัยที่จะบอกว่าฮาร์ดแวร์และรหัสของคุณเป็นปัจจัย จำกัด ไม่ใช่ JVM


คุณสามารถดูอีกครั้งได้ไหม ฉันอยากจะเห็นมันฟังดูน่าสนใจและสนับสนุนว่าภาษาที่ใช้งานได้ง่ายสามารถปรับข้ามแกนได้
Thorbjørn Ravn Andersen

คุณสามารถให้ลิงค์ไปยังสิ่งนั้นได้หรือไม่? ฉันรู้ว่า Cliff Click, Jr. หัวหน้าวิศวกรจาก Azul Systems ใช้การจำลองแบบ Ant Colony ของ Rich Hickey ในระบบ JCA ที่ใหญ่ที่สุดของ Azul (Azul Vega 3 Series 7300 Model 7380D: AzulSystems.Com/products/compute_appliance_specs.htm ) ด้วย 864 cores และ 768 GB RAM และ 700 มดสามารถจัดการได้สูงสุด 700 คอร์ แต่ 9000 คอร์นั้นน่าประทับใจทีเดียว เครื่องจักรแบบไหนกันนะ?
Jörg W Mittag

มันเป็น "มด" จำลองผมเชื่อว่า - นี่คือการเชื่อมโยงที่อุดมไปด้วย Hickey (Clojure ผู้สร้าง) พูดคุยเกี่ยวกับเรื่องนี้ - blip.tv/clojure/clojure-concurrency-819147 มันอยู่ในกล่องระบบ Azul ขนาดใหญ่ที่มีคอร์มากกว่า 800 คอร์ส่วนใหญ่ทำเพื่อแสดงให้เห็นว่า Clojure ดีเพียงใดในการจัดการการทำงานพร้อมกันของมัลติคอร์
mikera

@mikera lins หมดอายุแล้ว
Thorbjørn Ravn Andersen

2

หลังจากเล่นกับคลาส DieLikeACode ของ Charlie ดูเหมือนว่าขนาดของเธรด Java จะเป็นส่วนใหญ่ของจำนวนเธรดที่คุณสามารถสร้างได้

-Xss ตั้งค่าขนาดสแต็กของเธรด Java

ตัวอย่างเช่น

java -Xss100k DieLikeADog

แต่ Java มีส่วนติดต่อผู้บริหาร ฉันจะใช้สิ่งนั้นคุณจะสามารถส่งงาน Runnable หลายพันงานและให้ Executor ประมวลผลงานเหล่านั้นด้วยจำนวนเธรดที่แน่นอน


13
เราตั้งชื่อมันว่า DieLikeACat ได้ไหม? มันจะไม่ตายหรือไม่มีชีวิตจนกว่าคุณจะรันมัน
Goodwine

ขอบคุณสำหรับการชี้ไปที่ผู้บริหารควรใช้บ่อยกว่านี้ แต่มันจะไม่ทำงานหากRunnable/ Callableต้องการทำงานอย่างต่อเนื่องเช่นเมื่อต้องจัดการกับการสื่อสาร แต่มันเหมาะสำหรับการสืบค้น SQL
Matthieu


0

จำนวนเธรดสูงสุดขึ้นอยู่กับสิ่งต่อไปนี้:

  • การกำหนดค่าฮาร์ดแวร์เช่นไมโครโปรเซสเซอร์, RAM
  • ระบบปฏิบัติการไม่ว่าจะเป็นแบบ 32 บิตหรือ 64 บิต
  • รหัสภายในวิธีการเรียกใช้ ถ้ารหัสในวิธีการเรียกใช้มีขนาดใหญ่มากแล้ววัตถุเธรดเดียวจะมีความต้องการหน่วยความจำเพิ่มเติม

  • 0

    ข้อมูลเพิ่มเติมสำหรับระบบ linux ที่ทันสมัย ​​(systemd)

    มีทรัพยากรมากมายเกี่ยวกับค่านี้ที่อาจต้องมีการปรับแต่ง (เช่นวิธีเพิ่มจำนวนสูงสุดของเธรด JVM (Linux 64 บิต) ); อย่างไรก็ตามมีการกำหนดขีด จำกัด ใหม่ด้วยวิธี จำกัด systemd "TasksMax" ซึ่งตั้งค่า pids.max บน cgroup

    สำหรับเซสชันล็อกอินค่าดีฟอลต์ของUserTasksMaxคือ 33% ของขีด จำกัด เคอร์เนล pids_max (ปกติคือ 12,288) และสามารถแทนที่ได้ใน /etc/systemd/logind.conf

    สำหรับบริการDefaultTasksMaxค่าเริ่มต้นคือ 15% ของจำนวนเคอร์เนลที่ จำกัด pids_max (ปกติ 4,915) คุณสามารถแทนที่สำหรับบริการโดยการตั้งค่า TasksMax ใน "systemctl แก้ไข" หรืออัปเดต DefaultTasksMax ใน /etc/systemd/system.conf


    0

    ปี 2017 ... ชั้นเรียน DieLikeADog

    ใหม่เธรด # 92459 ข้อยกเว้นในเธรด "main" java.lang.OutOfMemoryError: ไม่สามารถสร้างเธรดดั้งเดิมใหม่

    i7-7700 16gb ram


    คำตอบนอกหลักสูตรจะแตกต่างกันไป ฉันได้ 1,0278 ที่มี RAM 6 GB
    jamie

    -4

    คุณสามารถประมวลผลเธรดจำนวนเท่าใดก็ได้ ไม่มีขีด จำกัด ฉันเรียกใช้รหัสต่อไปนี้ในขณะที่ดูภาพยนตร์และใช้ NetBeans และทำงานได้อย่างถูกต้อง / ไม่ต้องหยุดเครื่อง ฉันคิดว่าคุณสามารถเก็บกระทู้ได้มากกว่าที่โปรแกรมนี้ทำ

    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();
            }
        }
    }

    7
    ฉันรู้ว่านี่เป็นความคิดเห็นที่ล่าช้า แต่ฉันเชื่อว่าเหตุผลที่คุณสามารถเริ่มต้นและเรียกใช้เธรดจำนวนมากเหล่านี้เป็นเพราะ (สมมติว่าการกำหนดค่าระบบปกติและสมเหตุสมผล) แต่ละเธรดจะพิมพ์ออกมาหนึ่งบรรทัดจากนั้นไม่มีเหตุผลเพิ่มเติม มีอยู่และถูกฆ่าไม่นานหลังจากนั้นจึงมั่นใจได้ว่ามีทรัพยากรอย่างต่อเนื่อง
    ucsunil

    @ucsunil นั่นไม่ใช่ความจริง ฉันคิดว่าคุณอ่านรหัสผิด ฉันเพิ่งลองและเธรดอื่นกำลังพิมพ์ออกมาไม่ใช่แค่บรรทัดแรก แต่รวมถึงชื่อด้วย ซึ่งหมายความว่าพวกเขามีการใช้งาน หากคุณคิดว่าการเก็บขยะจะรีไซเคิลหัวข้อ unreferenced, มันไม่ได้ดูที่นี่
    Evgeni Sergeev

    1
    อย่างไรก็ตามหลังจากนั้นครู่หนึ่งmainก็จะโยนลงOutOfMemoryErrorบนเครื่องของฉันโดยบอกว่ามันไม่สามารถสร้างเธรดได้อีก บางที @AilPal คุณไม่สังเกตเห็นว่า ฉันขอแนะนำให้รวมคำสั่งการพิมพ์อื่นในmain(..)วิธีการเพื่อให้เห็นอย่างชัดเจนเมื่อสิ้นสุดการสร้างเธรดใหม่หลังจากทิ้งข้อผิดพลาด
    Evgeni Sergeev

    5
    น่าทึ่ง ... การค้นพบเครื่องทัวริงจริง ... ทรัพยากรไม่สิ้นสุด
    Josh
    โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
    Licensed under cc by-sa 3.0 with attribution required.